#技術書典5 エモ枠『セイチョウ・ジャーニー』『完全SIer脱出マニュアル』

小話

AとB、二人の会社員がいた。二人は同期で、今はたまたま同じプロジェクトに所属していた。


能力や、仕事に対する価値観が似通っていたためか、二人は親しい関係にあった。

プロジェクトも終わりに差し掛かったある日、二人は上司に会議室に呼ばれた。

「新しいプロジェクトが立ち上げられる予定である。そのプロジェクトは会社にとってチャレンジングなものだが、やる価値は非常に高い。君たちは興味あるかね?」

Aは迷った。あまりに唐突だったからだ。興味はそそられるが、ここでYesというべきか決めきれなかった。

Aが戸惑っている最中、Bが声を上げた。「ぜひやりたいです!」

かくしてBがその新しいプロジェクトにアサインされた。プロジェクトは困難を乗り越え大成功を収め、Bは次々と大きな仕事を任されるようになった。

一方Aは、良くも悪くも平均的なキャリアを進むこととなった。あのとき、先にAが声を上げていれば、立場は入れ替わっていたのかもしれない。

『セイチョウ・ジャーニー』

いきなり小話から入ってしまったが、要点は「何かを掴み取るには、声をすばやく上げることが大事」ということです。

技術書典5で『セイチョウ・ジャーニー』を著したGrowthfactionのメンバーは、てぃーびーさんのメンバー募集に「声をすばやく上げ」た人たちです。

tbpgr.hatenablog.com

*1

growthfaction.booth.pm

中身についての感想ですが、これまたてぃーびーさんのパートには共感するものがありました。ゲームをやりこんでいくことで、ゲームそのものの上達だけではなくて友達もできるという嬉しい経験は、私にもあります。

一方、これを仕事に当てはめようとすると、追加で考慮すべき要素が2つ増えます。1つはお金です。お金と成長はイコールではないものの密接に関わっていきます。もう1つはゴールが無数に存在することです。ゲームでは「最強」というゴールがポピュラーであり非常にわかりやすいですが、仕事に関しては自分なりの目標を立てていく必要があります。

さて、先程の小話にはもう一つ要点があります。それは、声を上げるためには自分の行きたいところがどこか決める必要がある、ということです。

チャンスは常に突然やってきます。それを掴み取れるか否かは、普段からそれを待ち構えているかによります。先程チャンスを掴んだBさんは、実は普段から目標についてアウトプットしていたり、すでに別の機会でのチャレンジを通じて、自分の目標をブラッシュアップしていました。だから、どのようなチャンスを自分が求めているか分かっているし、チャンスへのアンテナがビンビンに張られていたわけです。

『完全SIer脱出マニュアル』

転職に向かう舗装された高速道路、それがこの書籍です。

techbookfest.org

作中での「SIer」の定義は狭く、私はのっけからその定義から外れていました。しかし、「マニュアル」と題名にある通り、これに従っていけば転職できそうな印象を受けます。

特筆すべきは、これが著者のgamiさんだけはなく様々な方の経験を総合したものであるということです。これはPodcastしがないラジオ」で様々なゲストからキャリアを聞いてきたことが生きています。すると、マニュアルとしてバランスの取れたものになり、無用な失敗を経験せず済みます。

あと表紙めっちゃいいっすねこれ。

まとめ

とりあえずブログとツイッターのフォローを増やしました。

*1:boothのリンクを貼りたかったけど場所わかりませんでした。→教えていただきました(追記済み)

レビュー『金融に未来はあるか』

金融機関に勤める友人におすすめされたので買って読んでみました。

せっかくなので学んだことを書いてみたいと思います。前提知識は必要ないと思いますが、経済学の知識が多少あるとさらに読みやすいと思います。

なお私自身は一応経済学部を卒業したレベルで、現在の職業はSEです。

ギャンブルと保険の相違

書中の序盤で批判していたのは、金融取引の一部はギャンブルでしょというものです。例えば自分が病気になった時にお金がもらえる生命保険はリスクヘッジですが、いきすぎたCDSはただのギャンブルだよという主張です。 P51に賭けと保険の違いが述べられています。

1892年、競馬ファンだった判事のヘンリー・ホーキンス卿は、英国法における賭けの意味を次のように定義した。「二人の人物が、不確実な将来のある出来事について互いに反対の結果を予想すると明言し、その出来事の結果次第で一方が他方から金を獲得するという契約」であると。保険はこれとは異なる。ポッツのもう少しぎこちない表現によると、保険の本質とは「被保険者が想定する災難が起こった場合、それによって彼が被る不利益に鑑み、保証を行う契約」である。

いうまでもなく人類はギャンブルが好きです*1。そのうえ胴元は儲けやすく、ギャンブルの参加者はしばしば人生を破壊されます。こういう理由のため、ギャンブルは厳しく制限されています。しかし、金融機関はこういうギャンブル性の高い商品を売りまくっていましたよね?と筆者は批判を展開しています。

おまけに確率論的に計算可能な「リスク」だけではなく、どんなリスクが有るかすら分かっていないという「ブラックスワン」というのもあります。数学を駆使して新商品を生み出し、それを大量に流通させて持ち合うことで、誰がどんなリスクを取っているのか誰もわからなくなっていきました。「ブラックスワン」が現れやすい状況と言えるでしょう。

感想としては、「ギャンブルは胴元が儲かるってそれ一番言われてるから!!」です。あと一般論的に、人生におけるリスクの把握と管理はサボっちゃいけないよなと。

投資銀行の抱える利益相反

投資銀行利益相反を抱えているのは書中で何度も強調されていますが、P141にその構造が述べられています。

知識豊富な顧客は胴元の的である。(中略)事情通の参加者の存在が恐れられ、事情に疎い大半の顧客の足が遠のく恐れがあるからだ。だからこそ、「賭博場」にビジネスを呼び込むことと、賭けの対象であるリスクの根本的性質について広く知らしめることの間には、利害衝突が内在するのである。

賭博場という表現が当てはまるのは上で述べたとおりです。ちなみに、そのすぐ後で、トレーダーが顧客情報を使っていると書いてありました。そういう情報交換って禁止されているんじゃなかったっけ?と思いましたが、そのへんの線引きはちょっとよくわかりませんでした。

2008年の金融危機の引き金になったものに、住宅ローンの破綻があることは有名です。証券化したりリスク別に分解して販売したりと色々策を講じ、今まで貸せなかった人に貸しまくるようになりました。当然そのうち崩壊するのですが、証券を保有している金融機関は、実際どんなリスクがあるか把握できていません。そういう事もあって被害が拡大したのだと思います。

若干スルガ銀行に近いものを感じますね。あっちはもっと原始的というかダイレクトにアウトな気がしますが。

やはりいつの時代も割を食うのは情弱の一般市民ということですね。一生近寄らないか、めっちゃ勉強した上で最初は授業料を払う覚悟で臨むしかなさそう。

「大きすぎて潰せない」の訂正と投資銀行マンの報酬

「大きすぎて潰せない」という言葉は潰してしまうと経済に悪影響を及ぼしてしまうので、(主に政府が)その企業を救済するべきという意味です。先の金融危機では多くの金融機関が政府によって救済されました。しかし、それは「大きすぎて潰せない」というよりは「複雑過ぎて潰せない」というのが筆者の考えです。

金融機関がポジションをお互いに持ちあったために、正確な状況が誰にも把握できなくなり、「この銀行倒産したら影響が他の多数の銀行に及ぶのでは?金融システムやばくならない?」という懸念が沸き起こったということです。

なお、救済を受けた金融機関は全く反省しない……。その上、投資銀行の上層部への報酬はアホみたい高いと指摘しています。

全然関係ないけどプログラムは密結合ではなく疎結合にせよという原則を思い出しました。ぐちゃぐちゃにからみあったスパゲッティコードは変更するのが難しく、いざバグが見つかったときには大変なコストが発生します。

まとめ

他にも「高速取引のアルゴリズムの開発ばっかりやっていないでちゃんと本来の業務に集中しなさい」などの主張もありますがこのへんで締めたいと思います。

お金・金融関連の良作をいくつか読みたいと思っているので誰か教えてください。

*1:一般論です。ちなみに「自分ならうまくできる」という思い込みがギャンブルへの参加を加速させます

『試して理解 Linuxのしくみ 実験と図解で学ぶOSとハードウェアの基礎知識』後編

こちらの本、ようやく読み終わりました。

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

ちなみに前編はこちら alek3.hatenablog.com

前編を踏襲して各章軽くまとめます。詳細にいきたいですが私の理解があまり足りていない感じです。

第5章 メモリ管理

単純な物理メモリの管理ではいくつかの問題が発生するので、仮想記憶を使いますという話になります。前半の方でプロセスをランダムに落とすOOM Killerという恐ろしい子の話が印象的でした。なんでこんなのあるんだ……。

第6章 記憶階層

レジスタキャッシュメモリ、メモリ、ストレージデバイスという記憶装置の階層構造において、いかにレジスタとメモリ間でのアクセスを減らし、キャッシュメモリに収めるかという話です。 ちなみに1Gバイトのファイルをキャッシュする作業があるのですが、私のvagrant上での仮想マシンはメモリが1Gバイトしかないので全部がキャッシュされず、読み出しもほとんど速くならないという結果になりました。

第7章 ファイルシステム

ファイルシステムの不整合を防ぐために何をしているかについて詳しく書いてありました。原子性を保つためにジャーナリングやコピーオンライトという仕組みが用いられています。

第8章 ストレージデバイス

主にHDDの話になります。シーケンシャルアクセスとランダムアクセス、支援機能のありなし、読み出しか書き込みで対比させながら速度を比較していました。SSDになると速度が3~5倍になります。

全般

図がものすごくたくさんあるので分かった気になるのが良いです。特にメモリ管理の章はあるとないとでは理解に雲泥の差が生まれるような気がします。
Cのプログラムは全く読まずコピペで済ませました。それでも動くので楽しいです。
一方で、エントリ内の雰囲気から感じられたように1回の通読でそんなに理解できたかというとそうでもない気がします。*1

また、誤字がかなりあるので正誤表を手元において読み進めるのをオススメします。

参考

『[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識』読了 - Smoky God Express

*1:この本を出題範囲にした大学の期末試験があったらめっちゃ身につきそう

S3にファイルをアップロードしようとしたらPermission deniedされた[Java]

お仕事でハマった件について、解消に至る流れを記載します。先に教訓を書いて、以降問題解決に至るまでのプロセスを記載します。 なお解決したのは主に同僚だった模様。

教訓

  • スタックトレースを出すべし
  • ファイルに書き出さなくていいならインメモリで扱うべし
    • 一度インスタンスにしたFileを読み出し(書き込み?)しようとすると、permission errorが発生するかも。

事象

Webアプリの管理ページからファイルをS3にアップロードしようとするとエラーが発生します。
エラーメッセージは以下のみ。
java.io.FileNotFoundException: ファイル名 (Permission denied)

対処

スタックトレースを出す

エラーメッセージだけだとAWS側の設定に問題があるのかサーバー側のコードに問題があるのか分からないので、詳細なスタックトレースがほしいところです。

ログの出力はlog4jのLoggerを使っていました。
log4jのerrorメソッドは引数が(Throwable e)だけだとスタックトレースが表示されませんが、(String message, Throwable t)だと表示されるようになります。

これをもとに、ソースを以下の通り書き換えました。

  • 修正前
// 中略
catch (Exception e) {
    logger.error(e);
}
  • 修正後
// 中略
catch (Exception e) {
    logger.error("An error occurred during rendering an administrator page.", e);
}

補足として、log4jjavadocを取り上げます。

Logger (Apache Log4j API 2.11.1 API)

以下のerror(String message, Throwable t)を用いることで、スタックトレースを出力できるようになります。

error(String message, Throwable t)
Logs a message at the ERROR level including the stack trace of the Throwable t passed as parameter.

一方、Throwable t のみを引数にしたメソッドはなく、修正前は、error(Object message)が該当していて、スタックトレースが出力されていなかったようです。

Permission denied エラー解決

スタックトレースを見ると、一番下に以下の記載がありました。*1

Caused by: java.io.FileNotFoundException: ファイル名(Permission denied)
    at java.io.FileOutputStream.open0(Native Method) ~[?:1.8.0_171]
    at java.io.FileOutputStream.open(FileOutputStream.java:270) ~[?:1.8.0_171]
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213) ~[?:1.8.0_171]
    at java.io.FileOutputStream.<init>(FileOutputStream.java:162) ~[?:1.8.0_171]
    at fuga.hoge.S3FileStorage.upload(S3FileStorage.java:32) ~[***.jar:?]
    at fuga.hoge.BaseFileService.upload(BaseFileService.java:33) ~[***.jar:?]
    ... 89 more

S3FileStorage.javaが我々が作成したソースです。これを見ると、32行目は以下の行に相当します。

  • 修正前
@Override
public void upload(@NonNull String filename, @NonNull byte[] contents) throws IOException {
    File file = new File(filename);
    try (FileOutputStream fos = new FileOutputStream(file)) {  // ←ここ!!!!
        fos.write(contents);
        s3Client.putObject(Constants.S3_BUCKET_NAME, filename, file);
    }
}

try-with-resourceの冒頭で落ちている事がわかります。 作成したファイルインスタンスを操作できないのが原因とみられるので、ファイルではなくバッファー配列を作成しました。

  • 修正後
@Override
public void upload(@NonNull String filename, @NonNull byte[] contents) throws IOException {
    ObjectMetadata metadata = new ObjectMetadata();

    try (ByteArrayInputStream is = new ByteArrayInputStream(contents)) {
        s3Client.putObject(Constants.S3_BUCKET_NAME, filename, is, metadata);
    }
}

これで無事アップロードできるようになりました。
同僚曰く、File()はディスク上でファイルを作るからアクセスできないという問題が生じるんですよと言っていました。

振り返り

最初のエラーメッセージを見た時にAWSの問題かなと思ってうろたえていたのですが、冷静に振り返るとFileNotFoundExceptionなのでS3は関係ないんじゃないかと気づくべきでした。

もちろん、スタックトレースは出すべきで、それによって初めて原因箇所が特定できました。

そして最後の修正ですが、ファイルはS3にアップロードするのが目的でサーバーにとっておく必要がないので、そのような場合ではFileのようにディスクに書き込む方法ではなくインメモリで扱う方法がいいでしょう。

*1:JavaスタックトレースはCaused by hogehogeと続いていくので一番下から読んでいくと根本原因にたどり着けることが多い

デザインパターン「Observer」

仕事中に登場したので復習を兼ねて書きます。 デザインパターンの内容は結城浩『増補改訂版 Java言語で学ぶデザインパターン入門』を参照しています。

何がうれしいパターンなのか

観察対象(Subject*1)が変化したときに、観察者(Observer)に通知します。 状態変化に応じて、処理を記述できるようになります。

クラス図

f:id:alek3:20180924000503p:plain デザインパターン本で頻出の、交換可能性を実現しています。

右側のObseverはインタフェースでも可。例ではインタフェースになっていました。

なお、Observerパターン自体にはSubjectに変化をもたらすものは登場しないので、例ではSubject内にexecuteとして実装されています。

import java.util.ArrayList;
import java.util.Iterator;

// Subject
public abstract class NumberGenerator {
    private ArrayList observers = new ArrayList();
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
    public void deleteObserver(Observer observer) { 
        observers.remove(observer);
    }
    public void notifyObservers() {               
        Iterator it = observers.iterator();
        while (it.hasNext()) {
            Observer o = (Observer)it.next();
            o.update(this);
        }
    }
    public abstract int getNumber();  // getSubjectStatusにあたる
    public abstract void execute();  // デザインパターン範囲外
}
import java.util.Random;

// ConcreteSubject
public class RandomNumberGenerator extends NumberGenerator {
    private Random random = new Random();   
    private int number;             
    public int getNumber() { 
        return number;
    }
    public void execute() {
        for (int i = 0; i < 20; i++) {
            number = random.nextInt(50);
            notifyObservers();
        }
    }
}

java.util.ObserverインタフェースとObservableクラス

JDK1.0から、Observerパターンの一種がObserverインタフェースとObservableクラスによって備えられています。 しかし、書籍内では、subject役がObservableクラスを使う必要があるといった理由から、これらは使わずに自前で実装するのが良いとしています。

その主張は理解できますが、一方でその手法は原始的すぎるように感じ、より洗練された手法はないかと探してみることにしました。

Observerがdeprecatedになったことについて

stackoverflow.com

Java9になってObserverやObservableがdeprecatedになったと書いてあります。
その理由について、Raviさんは以下の通り述べています。

  • シリアライズできない
    • ObservableがSerializableを実装していないため
  • スレッドセーフでない
    • イベント通知の順番が保証されず、別のスレッドでも起きうる
  • イベントモデルがしょぼい
    • 何かが変わったという通知は出せるが、何が変わったかという情報が得られない

また、ベストアンサーにあるように、それらはレガシーコードであるため、直すより取り潰したほうが早いという総合的な理由があります。
全体的にそりゃdeprecatedされるわという印象です。

代わりに何を使うかという話ですが、java.beans.PropertyChangeListenerが挙げられています。

まとめ

やろうとしていることは理解できますが、その手段としては、Observerパターンそのものでは古いという印象を持ちます。そこらへんの進化とかモバイルの関わり*2とかを調べたかったのですが進みきれませんでした。

デザインパターンシリーズ

alek3.hatenablog.com

その他記事

qiita.com

タイトルの形式をここと同じように『デザインパターン「○○」』にしました。全般的にデザパタ本をかなり丸々引用していて大丈夫か感は少しだけありますが、噛み砕かれているのとプラスアルファの記載もあって読みやすいです。

*1:observableでもある

*2:RxJavaとかFlowなどのワードは出てきたが調べるところまで行っていない

伊藤祐策さんの「Webエンジニアの求人」ツイートに回答する

このツイート見て、見えっ張りな僕と自己評価の低い僕がせめぎ合いました。

見栄「いやいやさすがに全部わかるっしょ、ねぇ?」
自己「全部完璧に説明できるのかよ、俺には無理だよ説明してみろよさあ」
見栄「……一部調べて回答させていただきます。」

そんなわけで復習を兼ねてこれらのツイートの項目に回答していきます。 各項目の後ろの一言は、最初に頭に浮かんだ言葉です。

OSI参照モデルとは?~7つあるアレ~

OSI(Open Systems Interconnection)参照モデルとは、国際標準化機構(ISO)により策定されたコンピュータなどの通信機器の通信機能を、階層構造に分割したモデルです。*1

言い換えると、ネットワーク通信を相互に行うために制定されたプロトコルです。

OSI参照モデルは以下の7層で成り立っており、各層は互いに独立しています。

階層 名前
第7層 アプリケーション層
第6層 プレゼンテーション層
第5層 セション層
第4層 トランスポート層
第3層 ネットワーク層
第2層 データリンク層
第1層 物理層

それぞれの説明は長くなるので省略します。

TCP/IPとは?~4層あたりのアレ~

TCP/IPとは、現在のネットワークのデファクトスタンダードプロトコル*2です。 OSI参照モデルがあくまでモデルであるのに対し、TCP/IPは現在のネットワークで使われている技術の集合です。

TCPOSI参照モデルで言うところの主に第4層、IPは第3層にあたります。 それぞれどんな仕組みなのかは省略します。*3

POSTとGETの違い~動詞で考えればええ~

どちらもHTTPメソッドの一つです。

『Webを支える技術』では、以下の説明がなされています。

GETは指定したURIの情報を取得します。 POSTの代表的な機能は、あるリソースに対する子リソースの作成です。

Getは冪等であり(何度やっても結果が同じであり)、かつ安全であるが(既存のリソースに変化をもたらさない、すなわち副作用がないが)、POSTは冪等でなく、安全でもないという違いもあります。

SQLインジェクション対策~プレースホルダーでしょ?~

SQLインジェクションとは、主にWebアプリケーションの脆弱性をついて、任意のSQLを実行させることを言います。SQLインジェクションが成功してしまうと、保有しているデータが流出したり、改ざんされてしまったりします。そのためSQLインジェクションを防ぐための対策が絶対に必要になります。

有効な対策の一つには静的プレースホルダーがあります。要するにユーザーの入力を反映させる場所を予め決めておいて、実行されるSQLを想定内のものにする仕組みです。

XSSとは?~クロスをXって表すのかっこいい~

クロス・サイト・スクリプティングと読みます。 いわゆる徳丸本では、以下のように説明されています。

通常、Webアプリケーションには外部からの入力などに応じて表示が変化する箇所があり、この部分のHTML生成の実装に問題があると、クロスサイト・スクリプティング(Cross-Site Scripting)という脆弱性が生じます。

WebアプリケーションにXSS脆弱性がある場合、クッキー値を盗まれてなりすましの被害にあうといった問題が発生しえます。

サラッと書きましたが被害としては結構重いのでしっかり対策を打つ必要があります。

XSS脆弱性の対策としてあげられているのは、HTMLで特殊な意味を持つ記号文字(メタ文字)をエスケープすることです。

公開鍵暗号とは?~秘密鍵と公開鍵~

暗号とは他人に勝手に自分のファイルを読まれないように変換する手法ですが、暗号化するための「鍵」の種類は大きく2つあります。共通鍵と、公開鍵です。

公開鍵暗号方式では、自分しか持たない秘密鍵と、他人に公開する公開鍵があります。あるファイルを公開鍵で暗号化すると、それは自らが保有するペアの秘密鍵でのみ、復号できます。

公開鍵暗号方式は、暗号鍵をいかに安全に相手に渡すかという鍵配送問題を解決する方法であり、結城浩『暗号技術入門』では

公開鍵暗号は、暗号の歴史における最大の発明であるといえるでしょう。

と述べられています。

同書籍では公開鍵暗号の欠点も2点あげられています。

  • 対称暗号と比較して処理が何百倍も遅い
  • 公開鍵が信用できるものか判断しなければならない

これらの欠点を克服するための仕組みとして、それぞれハイブリット暗号システム、公開鍵の認証があります。

まとめ

説明足りないなという自覚はありますがこれくらいにさせてください。何も見ずにほぼ書ききったのもあればかなり調べて書いたものもありました。一方、どのトピックスでも「この本を読めば、またはこのサイトを見れば必要なことが書いてある」という状態にはなっていたのでそれは良かったかなと。

参考文献

『まんがでわかるLinuxシス管系女子①』まとめたった

まんがでわかるLinux シス管系女子(日経BP Next ICT選書)

まんがでわかるLinux シス管系女子(日経BP Next ICT選書)

まとめたった(死語)

前回記事の続きで、今回は既刊3巻中の最初の1巻を読みました。

前半(第1話~第13話)はLinuxの頻出コマンドが紹介されていて、後半(第14話~第24話)からシェルスクリプトの書き方の話になります。

後々私が振り返るために、トピックスを挙げておきます。

前半トピックス

  • 第1話:他のコンピュータをリモート操作したい
  • 第2話:一時的に管理者権限で操作したい
    • sudo
  • 第3話:さまざまな語句を一度に検索したい
    • grep
    • grep -r -i -E "((やまだ|山田) *(たろう|太郎) | yamada +tarou)" ディレクトリのパス
    • -rが再帰検索、-iがignore case、-Eが正規表現の使用
  • 第4話:端末でも対話的にファイルを編集したい
  • 第5話:vimでもコピー&ペースト&アンドゥしたい
    • vで選択モードに入る
  • 第6話:突然の回線切断から復帰したい
    • 仮想端末(ex.tmux)
  • 第7話:他の操作の結果を見ながら作業したい
    • 画面の分割
    • 縦横の分割が可能
  • 第8話:最近実行したコマンドを呼び出したい
    • 上下キーとCtrl+r
  • 第9話:ずっと前に実行したコマンドを呼び出したい
  • 第10話:ネットワーク越しにファイルをコピーしたい
    • scp。双方向可能
  • 第11話:システムの過負荷を把握したい
    • top
  • 第12話:システムのメモリー不足を把握したい
    • sudo service apache2 restart
  • 第13話:ログファイルから必要な行だけ取り出したい
    • パイプライン、zcat

後半トピックス

話数を省略して、トピックスだけ挙げます。

後ろの方になっていくほど、普通のプログラミング言語の話と同じになっていくのが面白かったです。 仕事で引き継いだシェルスクリプトカイゼンしていくヒントにしようかなと思いました。

関係ないけどみんとちゃんがGUI派から割とすぐにCUI派に転向していくのに成長スピードの速さを感じました。

喜怒哀楽の大きさは最初から健在で読んでて楽しいです。