ななめよみ・高卒でもわかる機械学習(2)
CouseraのMachine Learningコース受講前に日本語でざっくり情報を入れるために、高卒でもわかる機械学習 (0) 前置き | 頭の中に思い浮かべた時にはを読む。
今回はその2から。 パーセプトロンなるものについて解説するらしい。
単純パーセプトロン
前回学んだ、メールがスパムかどうかを判定するグラフを指す。 複数の入力に重みをかけあわせて、結果が0より大きければ1を返し、0以下なら0を返す。
これがニューラルネットワークの基本単位。 そしてこの「重み」をベクトルにして自動計算するのが機械学習というわけか。
どうやって重みを更新するのか?
その手順は、 - 最初はランダムな値を設定する - その重みを使って教師データを解いてみる - 間違いに対して、正しそうな方向に重みを微修正してリトライ - 繰り返し
である。
まずある関数がどれくらい教師データに対して期待はずれだったかを表す「損失関数」を想定する。 この関数の最小値を取れれば、そいつが単純パーセプトロンの最も期待どおりに振る舞う重みだと判定できる。
最小値を求めるためには、今の座標での関数の傾きを求め、それが正なら小さく、負なら大きくなるように少しずつ調整していくと良い。 (とはいえこれだと、谷が複数ある損失関数が書ける場合に失敗する気がする。)
この「少しずつ」の割合はそのままだと大きすぎて収束しないので「学習率」と呼ばれる定数をかけあわせてうまく収束するように調整する。
これを勾配降下法と呼ぶ。
これを使って重みを微調整した結果、最終的に重みの更新が全くなくなれば学習が終了する。
出力する
勾配降下法を使って重みを調整し学習したモデルは、与えられた入力に対して何か別の値を出力する。 たとえばスパム判定なら1 or -1、みたいな。 「○○らしさ」を数値化したものを入力に使って、外部に公開する値を生成する関数を「活性化関数」と呼ぶ。
スパム判定は二値判定であり、スパムなら0より大きく、そうでないなら0より小さい値がモデルから返るので、 - モデルの返却値 >= 0 ならば 1 - モデルの返却値 < 0 ならば -1
となる関数を定義するとわかりやすい。
多分多層パーセプトロンっていうのは、神経回路みたいに単純パーセプトロンを何層も積み重ねて活性化関数で出力された値を次のパーセプトロンに引き継ぐモノなんだろうな。
多層パーセプトロン
単純パーセプトロンにはできないことがあって、それがXOR問題である。つまり、単純に1本のグラフで分けられないような集合に対しては何もできないのだ。 これは前に学んだ言葉でいう「線形識別不可能」なデータだといえる。
これを解決するのが多層パーセプトロンである。 XORに代表される線形識別不可能なデータは、線形識別可能な関数を複数個組み合わせることで実現できる。 こうして積み重ねられた複数の単純パーセプトロンを組み合わせたものが、多層パーセプトロンである。
この多層パーセプトロンにおいて、最初の層を入力層、最後の層を出力層、そして間のすべてを中間層と呼ぶ。
ではこの重みはどう計算するのかだが、ここから先は計算式が多すぎて理解できない。 今回は雰囲気を知るのが目的なので、微積分・ベクトルの知識を仕入れてリトライすることとして読み飛ばす。 ただ、多層パーセプトロンの重みを更新するためには「逆伝播」と呼ばれる方法を使うことはわかった。つまり計算時は入力層から順番に計算を進めるが、重みの更新時は出力層から順番に更新していくらしい。
斜め読み - 高卒でもわかる機械学習
とうとう機械学習を使えるようになろうと思うので、手始めに
をざっと読んで全体像をつかむことにした。
1回目なのでまずは斜め読みして、2回目以降もう少し知識がついた時に詳しく読むことにする。 斜め読みはするが、筆者の方には勿論感謝と敬意を払っている。
記事自体は2年前のものなので今はまた違うのかもしれないが、なんにせよ基礎を知るのは悪いことではないはず。
機械学習を学ぶ最終目標
たとえばあるスキルセットをもったエンジニアに対してどれくらいの給与を提示するのが市場の相場か?を算定してみたい。 つまり 0 or 1 ではなく具体的な数値をアウトプットする機械学習アプリケーションを構築したい。
機械学習が解決してくれる問題の種類
- 分類問題: 入力が何かに分類できると判断する(ex. 猫画像判定)
- 回帰問題: 入力から新しい情報を生成する(ex. 降水確率予想)
どっちを解決するかはアルゴリズムの「評価関数」によって決まる。
機械学習の種類
種類があるらしい。そりゃそうか。ニューラルネットワークとか?と思ったけど違うらしい。
- 識別関数: 入力があるものに分別できるか判定する(ex. スパム判定)
- 識別モデル: ???
- 生成モデル: 入力を使って新しい情報を生成する(ex. 自然な日本語の文章を自動生成する)
識別関数が一番初歩的でとっつきやすいらい。
機械学習の成果の正しさ
学習の仕方が間違っている時と、判定が間違っている時がある。 たとえばある入力値がA,B,Cのどれに所属するか調べる時に以下のような表が組める。
No | Aの確率 | Bの確率 | Cの確率 | 正解 |
---|---|---|---|---|
1 | 0.36 | 0.30 | 0.33 | A |
2 | 0.9 | 0.06 | 0.04 | B |
No.1では確率がバラけないので、学習が間違っているかもしれない。 No.2では確率はバラけているが、判定結果が間違っている。
識別関数とは
入力値を「素性」と呼ばれるデータにバラす。 そして真な結果に何回出現したか調べる。 それに従ってテストデータを解析し、真な結果に多く見られるデータが何回出てきたかでテストデータの真偽判定を行う。 メールのスパム判定機とかが作れる。
数学的には、ある平面にプロットされた学習用データのうち、真と判定されるものと偽と判定されるものをキレイに2分する関数を導出することといえる。
線形分離可能とは、ある関数によってスッパリ分けられること
上述のように、ある空間上にプロットされたテストデータ郡をスッパリと2つに分けられる関数が存在する場合、それを「線形分離可能」と呼ぶことができる。
これができない問題は「線形分離不可能」と呼ばれる。点がめちゃめちゃに入り混じっている問題は線形分離可能な問題と同じ手法では解くことができない。
参考文献
今度こそ受け切るCoursera Machine Learning
来たる12/11から、また新学期が始まるようです。
これまで2度受講してそのうちどちらも最初のIntroductionの課題を先送りにして挫折した僕も、もうさすがに自分のスキルセットに機械学習の基礎がほしいので、今度こそ受けきってみせる。
ductとataraxyでふつうのWebサイトを作る
「ふつう」には全く深い意味はなくて、ただただHTMLをGETできてPOSTリクエストを受け付けられるふつうのWebサイトを作ろうとしてみた。 ふつうすぎて逆に情報がなかったのでまとめてみる。
バージョン情報
- duct: 0.6.1
前提知識
やったこと
とりあえずプロジェクト生成する
lein new duct sample +site +example
DBは置いておく。作者が書いたAPIサーバーを作れるブログエントリがあるのでそれを見れば触れるようになると思う。ここで出てくるboundaryという概念もクールだなーと思ったけどそれはまたいつか。
とりあえずエディターからREPLにつなぐ
おもむろにEmacsを立ち上げてcider-jackinする。
動かしてみる
この時点で localhost:3000/example にアクセスするとサンプルページが出る。
formを書く
[hiccup "1.0.5"]
を依存に追加して以下のようなコードを書いてみる
[::response/ok (html [:h1 "hello"] (form-to [:post "/example"] [:p (label {} "username" "username") (text-field {:placeholder "username"} "username")] [:p (label {} "email" "email") (email-field {:placeholder "foo@example.com"} "email")] [:p (label {} "password" "password") (password-field {:placeholder "your password"} "password")] (anti-forgery-field) [:p (submit-button {} "submit")]))]
すると localhost:3000/example で
みたいな画面が見える。
POSTする
ルーティングをいじる。
:duct.module/ataraxy {"/example" {[:get] [:example/new] [:post {user :params}] [:example/create user]}} :sample.handler.example/new {} :sample.handler.example/create {}
で、関数のnamespaceとかも書き換える。
(defmethod ig/init-key ::new [_ options] (fn [what-is-this] (println what-is-this) [::response/ok (html ;; 省略 )])) (defmethod ig/init-key ::create [_ options] (fn [{[_ user] :ataraxy/result}] (println user) [::response/ok "created"]))
この状態で localhost:3000/example にアクセスしてformを送信すると画面遷移するし、REPLにリクエスト情報が出てくる。 やったぜ。
リクエスト自体をもらいたくなったらどうする?
routing時点でのデスラクチャリングはataraxyの強みだけど、もしもっとガツッとほしくなったら? その時はhandlerの無名関数が受け取る引数を、バラさずにそのまま受け取れば中にリクエスト内容が全部入ってる。
anti-forgeryとかのミドルウェアどこで差し込まれてるの?
がconfig.ednに差し込まれてて、うまいことデフォルト値を定義してくれているよ。 定義内容が知りたければREPLで
(prep) (pprint config)
したらわかる。
感想
しばらく前にClojure始めてよかったなーという気持ちしか沸かないくらい過去の資産をうまーく組み合わせて実現されてた。 これだけのエコシステムを数年かけて作ってきたring / ductのコミュニティとそれを牽引したweavejester本当にすごいな。
Spring Fest 2017 Fallに参加してきた
弊社がいいよって言ってくれたので、弊社Springframework率ゼロに等しいのに平日に1日使って仕事としてSpring Fest 2017 Fallに参加してきた。弊社ありがとう。
聞いてきた話を感想や学びと一緒にまとめておく。
NOTE : 間違いのないように気をつけてはいますが、誤解している箇所があればぜひ後学のためにご指摘ください。
普段Javaを触らない各位のために
ちょっとだけ解説すると、SpringframeworkはJava製のアプリケーションフレームワーク。 数年前まではいくつかのフレームワークがあったが、現在は一強になりつつあるように思う。 オブジェクトをDIで組み合わせて巨大なアプリケーションを構築できるのが特徴。
リクルートホールディングスやYahoo!Japanなどのメガ企業にはじまり、様々な企業が採用している。私が浅学なだけで山ほど採用企業はある。
基調講演: What's new in Spring?
Pivotalの強い人で、Springframeworkファミリーの様々なプロダクトの開発に関わってきたDave Syer氏による基調講演。 穏やかな話し方をする方だった。イケるやろと思って同時通訳なしでチャレンジしてみたら半分くらいしかわからなかった。
スライドは以下。
注 PivotalはSpringframeworkのメンテナ企業。Pivotal Cloud FoundryというクラウドプラットフォームやConcourse CIも開発している。
Springプロダクトのレイヤーについての概要
Springframeworkの各プロダクトは、大きく分けて3階層で構成されている。 生SpringframeworkとSpring Boot、そしてSpring Cloudである。
Spring Bootを使うと生Springframeworkで辛かった設定の管理が簡単になって、Spring Cloudができたことで分散アプリケーションを開発できるようになった。
直近のアップデート内容
2017/11にかなりいろいろアップデートがあった。 Framework自体5.x系に上がったし、Securityも5.0.0.RC1に。Bootは2.0.0に。 Project Reactorというのもあって、WebsocketサポートとかReactiveなアプリケーション開発の基盤を提供している。
Spring 5.0ができること
以下のような変更を行っている。
- パフォーマンス改善
- Functional bean configuration(設定をもっと簡単に書ける)
- ReactiveにWebFluxとRouter Functionsを追加(イベントループ型の処理を可能にする)
- JUnit5サポート(最新のテストライブラリに対応)
- JDK9サポート(最新のJavaに対応)
- HTTP2サポート
- Kotlinサポート
Project Reactorについて
今までは、IOExceptionを起こしうる操作はtry-catchしなければいけなくて、Imperative(命令的)でBlockingだった。 でもFunctionalスタイルだと、Mono型を返してdoOnErrorでエラー処理できるのでNon-blocking。
注 Javaではもともと、1つのHTTPリクエストに対して1スレッドを起動するモデルでWebアプリケーションを開発する必要があって、つまり大量のリクエストを一度に受け付けるとスレッドが枯渇してしまう問題があった。 それに対する解決策としてSpring 5.0で提供されたのがFunctional Routerで、これでNode.jsに代表されるイベントループの仕組みをSpringframeworkが実現できるようになる。
Controller層もReactiveに書けるようになった!ControllerからMono型を返せる。 ただしWebFluxを使うと組み込みサーバーがNettyになる。TomcatはNon-blockingをサポートしないので。
新しいAPIクライアント
WebClientを使うと、APIアクセスする時にWebClient.create()してそのまま使える。 書き方はBuilderパターンみたいになっていて、client.get()...とメソッドチェーンをつなげていって、結果Reactiveなオブジェクトを取得できたりする。 テスト用のモックオブジェクトなども用意されていてテスタブル。
Cloud
Spring Cloud Function / Spring Cloud Gatewayが2018Q1、SpringBoot2.0.Xに計画されている。 FaaSをSpringで書けたり、API GatewayをSpringで書けたりするようになるらしい。これまた楽しそうなテーマ...!
所感
最近さらに、どの言語でやるかではなく何をするかに集中できるようになってきた気がする。 JavaでもRailsでもそれ以外でも、ノンブロッキングIOが使いたくて使えるならそれでいいし、dev.toみたいに適切にCDNを噛ませれば早くなる。
Functional Routerは書き方の問題じゃないか?なんでフィーチャーされてるんだ?と思ってたので、Dave Syer氏に質問してきた。 いわく、「Function」Routerとはいうけど実際にはFunctionalであることよりもリソースの削減ができるのが良い。これがない時代には、何百ものクライアントからの接続をさばく時山ほどスレッドプールを用意して処理が終わるまでスレッドプールを開放できなかった。でもFunctional RouterやMonoを返すようなControllerを書けばスレッドプールのリソースを削減できる。だから、たしかにFunctionalなのはtaste(好み)の問題だけど、良いことはある。
Introduction to Spring WebFlux
Pivotalの中の人になったmakingさん。
スライドは一度公開されたのだが現在非公開設定の模様。 アウトラインはgistにあがっている。
まずWebFluxを使ったデモアプリケーションのお披露目があった。
このデモアプリケーションはIoTデバイスからの通信を受け取ってリアルタイムにさばくアプリケーションで、このセッションを聞くために集まった聴衆からの80ほどのリクエストをさばいていた。 Tomcatは1リクエスト1スレッド消費するので、普通に書くとリクエストの数だけスレッドを消費するはずだが、このアプリはWebFluxというReactive Programmingの基盤を使っているので、5-10スレッドでさばける。なんだそれすごい!!!
Springに追加されたReactive StackはNon-Blockingを扱う。
今までのServlet Stackは1リクエストごとに1スレッドを生成するが、Reactive Stackはイベントループを使って処理を行うので、少ないスレッド数で処理を行える。具体的には、Tomcatがデフォルトで200のスレッドプールまで対応するのに比べてWebFluxはデフォルトでCPU数と同じ数だけのスレッドを使いまわしてスレッド数の10倍の数のリクエストを捌く。
Reactive Stream自体はJava API仕様で、SubscriberとPublisherが存在する。 Java9 APIでもRxJavaでもSpring ReactorでもAkka Streamsでも使える。 Flux(0..n件用)とMono(0..1件用)というインターフェースが重要。
Publisher側は情報を流す量を調整できて、1秒ごとに情報を流す、みたいなことができる。
Spring MVCとSpring WebFluxの違い
全く同じコードベースでも動くがそのままだと同期的なコードのままになるので、Mono.fromCallableとかを使ってMono型やFlux型を返す。 Spring MVC上でMonoを使うこともできる。が、非同期処理専用スレッドを立ててそいつを同期的に動かすことになる。(?)
無限ストリーム
content-typeをstreamに指定すると、無限ストリームを受け取ることができる。 使えるのは以下 - text/event-stream - application/stream+json - application/json
BackPressureを調整できるcontent-typeは上の2つだけ。これが効いてるとサーバー側でよしなにBackPressureを調整してくれるので、サーバーが圧倒されることがなくなる。(?)
POSTする時にRequest BodyをFluxでもらうこともできて、これをやるとリクエストが終わる前にレスポンスが返りはじめる。 Transfer-encoding: chunkedにするとじわじわとHTTPリクエストを送ることができる。
Streamをshare()すると、Streamがブロードキャストされて接続してきた人全員に同じストリームを配信できる。
Blockingなコードを使う時は気をつけて
Reactive StuckでBlockingなコードを書かなきゃいけない時は、あっさりCPUコア数分のリソースを食いつぶす。
Spring Data Kay
Reactiveサポートが入った。RedisとかのNoSQLとの通信でReactiveなインターフェースを扱えるようになった。 Repositoryのインターフェースが変わったので、バージョンをあげるとそのままでは動かないかも。気をつけて。
JDBCはReactorと一緒に使うとブロッキングになる。 具体的にはJDBC自体がブロッキングなI/Oしか提供しないので、イベントループ型のControllerなどを書いても結局JDBCアクセスで詰まってしまう。 すると、CPUコア数しかスレッドがないのでパフォーマンスが落ちる。 次のJavaでは非同期JDBCが入るはずなので、それを待つ方が良い。
だから、RDBMSにつなぐアプリケーションはWebFluxじゃない方が良い。
また、Spring SecurityもReactive用の設定がある。 ThymeleafでもReactiveモードがあって、chunked modeをサポートしてる。
これからWebFluxを使いたい時は、 FrontendにWebFlux、BackendのRDBがある時はSpring MVCで作ると良い。 BackendもWebFluxを取り入れたい時はNoSQLが必須。
Spring Cloud GatewayでAPI GatewayをSpringで作れるようになる。
所感
Reactiveに胸躍った。 Javaレベルが足りなくてスレッドを生成するコストとか保持するコストのイメージが沸かない。 でもAndroidでUIスレッドとBackendスレッドを使いわけるコードを書いたおかげで、ちょっとは分かる。
Yahoo! JAPANのコンテンツ・プラットフォームを支えるSpring Cloud Streamによるマイクロサービスアーキテクチャ
コンテンツプラットフォームというYJ内部の基盤開発の話。 スライドは以下。
コンテンツとは
天気、スポーツの試合情報、ニュースなど...。
コンテンツプラットフォームとは
個人・企業などの配信者から入稿されたコンテンツを管理する基盤。 リプレイス前はC+Perlの巨大なアプリケーションでテスト不可能・リファクタ不可能。
リプレイスの設計
処理自体は文字列の処理が中心なのでPaaSに行けるはず。 スパイクアクセスに耐えられるよう柔軟にしたい。 MQで非同期に処理を流したい。 データストアはCassandra。YJ!っぽい。 入稿受付サービス、入稿処理サービス(形態素解析、ジャンル判定など)、入稿通知サービスなど20ほどのサービスが連携してPivotal Cloud Foundryで動いている。 (ここらへんの仕組みが必要な点は、弊社にも共通する。本筋と少し違うけど、入稿するデータごとの違いはどうモデリングしてるんだろう。) 非同期部分はSpring Cloud StreamとApache Pulsar。 Apache PulsarはYahoo.Inc製のMQ。
Spring Cloud Stream
Source Processor Sinkの概念がある。 Brokerが必要。 テストツールでBrokerをモック化してテストできる。
つくってみて得た知見
処理のどこでエラーが発生したのか、関連するどのサービスが原因なのかわからない。 これを解決するために、Spring Cloud Sleuthを使ってリクエストごとに一意のIDを振る。 これにさらにZipkinを組み合わせてIDを可視化することができる。
所感
弊社も規模は比較にならないくらい小さいといえど、入稿 -> 配信の流れは同じ。 同じようにキューを挟んでマイクロサービス化するのはアリだと思う。
ドメイン駆動設計のためのSpringの上手な使い方
「現場で役立つシステム設計の原則」の著者、Guildworksの増田さんによるセッション。 博士みたいな風貌のおじいちゃん。
スライドは以下。
www.slideshare.net
DDDの魅力
サックと作ってリリースして終わり、であればいらない。 長く保守し続けること,価値を生み続けることが真意である。
DDDの基本活動
開発者がドメインを学ぶ
学んだことを"コード"として書けることこそ技術者 「継続的に学習する」 深い洞察に進む、姿勢
学んだことをコードで表現する
技術者たるものドメインの知識をコードで表現できる、説明できること
モデルと実装(の構造)を一致させる
- モデルと実装を関連付けることで、実装が整理され見通しが良くなる 実装からfeedbackすることで、モデルが実用的になる
テクニック
- ドメインの記述を 技術の関心事から独立させる isolating-the-domain
- 概念の単位とプログラミングの単位を一致させる
- モジュール化
- 型(class interface enum)で知識を表現する
- 基本データ型ではなく、ユーザ定義型で表現する
- 最初からピッタリの方は見つからない
- [実験 feedback 設計]の改善を繰り返す
深いモデルを探求する
- 正直言って... ここの議論はされていない。 (エバンス本の9-13章だったかな...?)
成果を最大化するために必要な作業だ
中核の複雑さ/機会に焦点を合わせる "中核"を探す作業こそが "モデルの探求作業"
- 役に立つ型を見つけるための実験を繰り返す
- 暗黙の概念を明示的に表現する
- 制約 (BeanValidation, Policy)
- プロセス (業務の流れ/手順)
- 区分の分析 「12の区分を分析したときに、3種類の状態の組み合わせだったなど」 -> 暗黙の知識を宣言的に表現できると if文がどんどん減っていく!!
- 暗黙の概念を明示的に表現する
巨大な複雑さに立ち向かう
- 戦略的に取り組む
- 時間がかかる
- 地道な努力の積み重ねのエネルギー
- 巨大な複雑さに立ち向かうためのスキル (14-16章)
巨大になればなるほど如何にシンプルな構造を見つけるか
「コードとしてどう表現するか?」
- 俯瞰
- 蒸留
- 大きな構造化
SpringとDDD
Springのprograming-model
Springはアプリケーションの「基盤」を提供する 開発者はドメイン固有のロジックに集中する ドメイン駆動設計の考え方そのもの -> SpringはDDDを実践するためのフレームワーク (@Service, @RepositoryはDDD本からでてきているのだ)
Springを使えばDDDになる?
MVCのモデル(@Controller/@Service/@Repository)をやっているだけでは(サービス層にスクリプトをゴリゴリ書くだけでは)得られない -> この3層からドメインを抽出することで初めて効果が得られる
DDDのためのSpringの使い方
spring-boot-starter-*
- 初日から...
- 動くアプリケーションで考える
- 学んだことをコードで記録する
- コードでモデルを表現する
- End to Endで実験してみる
spring integration
「巨大な複雑さに立ち向かう」 - 境界づけられたコンテキスト (Bounded Context) = gitリポジトリ単位 - コンテキストマップ - EIPの実装技術 分析・設計・実装するための枠組み - Messaging Model
spring batch
- 今でも多くの業務を裏で支えている
- ドメインの理解度の違いが現れる場所
- job/step etc.
まとめ(DDDを現場で取り組むためのヒント)
日本一やさしく説明する予定のマイクロサービス入門
JSUG会長長谷川さんのセッション。 スライドは以下。
www.slideshare.net
メッセージングでコラボレーションを行いつつ全体で1つの仕事をする、自立分散協調のアーキテクチャ。 オブジェクト指向をシステムレベルに適用した、と考えることができる。 マイクロサービスにはチームや会社のチームワークが必要だよ。でもそれもオブジェクト指向からの拡張と考えれば同じ。
オブジェクト指向が騒がれた当初、小さすぎるクラスや神クラスを作ってしまって今笑い話になるように、マイクロサービスに関してもそうなると思う。 今は大きすぎたり小さすぎるマイクロサービスを作ってしまうことがあると思うけど、正解は一つじゃない。
複雑なものは新しい技術で簡単にはならない!!! 今すごく複雑な業務プロセスを、マイクロサービスで簡単にするんだ!みたいなのは通用しない。 また新しい複雑なものができるだけ。
本当に簡単にしたければ、やり方を変えるしかない。業務プロセスを変えるとかね。
データモデルがぐちゃぐちゃだと、マイクロサービス化をそもそもできない場合がある。 Mybatis便利だよね、と言っている時点でなにかおかしくて、やばいSQLが書いてあるのでは?
最初から最高を目指さずに、切り出せるところから切り出していった方がいい。
マイクロサービスが増えると、「誰も知らないサービス」が出てきそう。100とか200のマイクロサービスを作ったとして、全体の仕様を管理できない、復元もできないみたいなことになる。 開発チームがバラバラ、RDB製品もバラバラでは、今後それをマネジメントする人がいなくなったらどうするのか? 全部SpringBoot x Javaで揃えた方が良いのでは? あるいは本当に必要なところだけ、その特性を活かしてNodeなりRubyなりつかえばよいと思う。
所感
最近あんまりマイクロサービスについての議論を追っていなかったけど、納得感のある話。 今はまだ提唱されてからの時間が短すぎて、今後どうなるかわからない。 でも今時点で試す価値は十分にある。要点を間違えなければ。
The Road to Serverless: Spring Cloud Function
Cloud abstractionについて話す。 Spring Cloud Functionについて話す。 Raising the value lineについて話す。
スライドは以下。
The Road to Serverless: Spring Cloud Function
Cloud Abstraction
VMから始まってコンテナ、アプリケーション、Functionの順に抽象度を増していく。
Serverlessはイベント・ドリブン、動的リソース最適化、メッセージに対して課金され、プロダクションコードを極めて高速に開発できる。 ビジネスロジックに集中できる。
Google Cloud Functionはなかなか良いよ。 WebUIで試せるよ。もちろんちゃんとやるならこれじゃダメだけど。CIが必要だし自動化が必要。
Spring Boot Thin Launcherってのがあるよ。
SpringでOAuth 2.0 / OpenID Connect 1.0を使う
実インスタンスを初めて目視確認したうらがみさんのセッション。
SpringでOAuth 2.0・OpenID Connect 1.0を使う
OAuth 2.0は仕様の日本語訳があるから見てみてね。 もちろんリソースオーナーもそれを利用する側もSpringで作れる。
cloud-oauth2を依存に追加する。 @EnableAuthorizationServerアノテーションで、それ用のエンドポイントとかが作られる。
アノテーションとapplication.propertiesの設定でSpring Securityを使ってOAuth2による認可を使ったログインが可能になる。
OIDCのくわしい仕様とかは話さない。
所感
OIDCまわりが全然前提知識として足りず、ついていけなかったので勉強する。 TwitterのOAuthログインも、専用ライブラリに頼らないでもここらへんを使うと作れるのかな。 要はユーザーの名前とかアイコン画像、メールアドレスを取得できればいいわけだしね。
まとめ
Springframeworkは今、特にクラウドネイティブ・非同期処理・マイクロサービスまわりのエコシステムが整ってきていると感じた。 NetflixやPivotalのような企業がJavaやSpringframeworkの周辺ツールを提供してくれているおかげでこのような環境が整ってきた。
たしかにマイクロサービスをやろうと思ってエコシステムから作るはしんどい。 すると、アプリケーション開発言語はエコシステムがどの程度整っているかで選ぶのも筋が悪くはないのでは?と思う。 PHPにはPHPに得意な、RailsにはRailsに得意な、SpringにはSpringに得意な領域がある。 そして現状Springのそれは、マイクロサービス開発に関わる部分のようだ。
文章を見直す、って何を見直せばいいのかまとめてみた - 箇条書き・表組み編
前回は単に日本語を連ねた文章のチェック方法についてまとめたが、同僚氏の文章をよくよく見てみると実際にはドキュメント管理ツールの機能を使うことによって論理的でない文章が隠蔽されていることがあることがわかった。
ので、今回はこれらの機能を使って書かれた文章をどの観点でチェックすべきか、について考えてみる。
箇条書き
箇条書きにすると接続詞を飛ばせるので、なんとなく論理的に整っているような気がしてしまう。自分もそうだった。 暗黙的に接続詞を伝えるのは難しいのだが、慣れないうちはそういう機能を使うとそれっぽくなる気がしてついつい使ってしまう。
ので、自分で書いた文章に箇条書きが含まれる場合は以下を行う。
明示的に接続詞をつけて読んでみる
箇条書きの兄弟要素は
- 理由の列挙
- 事例の列挙
であることが多いので、「また、」や「さらに」などの接続詞を使って読んでみる。
- 全文検索エンジンにElasticSearchを使う場合 (または) - 同じくSolrを使う場合
箇条書きの親子要素はより詳細な理由を説明することが多いので、「${親}。なぜなら${子}だから。」と読んでみる。意味が通らなければ直す。またはその項を消す。
- 外部アクセスできる必要がある - サーバーからS3にアクセスしなければいけない
表組み
表も難しい仕組みのひとつ。うっかり行・列の項目設定を間違えるとあっさり泥沼にハマることができる。 表組みを書いた時は以下のことをチェックする。
見出しをつける
表が何を示すのか、1行で述べる。
## S3とcronを採用した場合のメリデメの比較検討 | |メリット |デメリット | |:------|:--------------|:--------------------------------| |S3のhook|リードタイムが少ない|外部からのリクエストを受け付ける口が必要 | |cron |全部Rubyで書ける |実行タイミング次第ではリードタイムが長くなる|
見出しの内容と表組みの行ラベル(S3のhook)・列ラベル(メリット)の設定がズレている場合、言いたいこととズレた表を書いている。 あるいは見出しだけを読んで何の表がつづくのかわからない場合、言いたいことが何なのかまだまとまっていない。
ラベルと具体的な内容をつなげて読んでみる
ラベルをつけて分類するとなんとなく分類できているような気がするが実態が本当にそうかとは全く関係がない。 自分の表が論理的に正しい分類をしているかを調べるためには、見出しと具体的な内容をつなげて日本語にして読んでみる。
- S3のhookのメリットは、リードタイムが少ないことだ。 - cronのデメリットは、実行タイミング次第ではリードタイムが長くなることだ。
読んでいて違和感があれば、書いてある内容がズレているので直す。
文章を見直す、って何を見直せばいいのかまとめてみた
同僚の資料を添削する機会があって、添削と議論の中でわかったことをまとめておく。
NOTE: ここで資料とは、要件を議論するたたき台資料とか設計の選択肢の検討資料を指す。
正直自分も同僚と同じ年代の頃に「これロジカルじゃないよ」とか言われても、いや分からんなぁ...と思ってたし、その時にこんなことを分かってればもう少しうまいことやれたのかなぁ、と思いつつ。
自分が書いた文章を例文として拝借されることを快諾してくれた同僚氏、ありがとう。
資料を構成する要素を一つずつチェックする
資料を構成する一番小さな要素から順にチェックしていく。
資料は
- 単語
- 文
- 段落
- 章
が集まってできている。 チェックの観点は、これら一つ一つが日本語として正しいことと論理的に正しいこと。
単語
PCで書くなら関係ないけど、存在しない日本語を書いていないか調べる。 論理構造はないので調べない。
文
同音異義語を使い間違えていないか調べる。
破戒的変更を許容します。
日本語として「てにをは」が破綻していないか調べる。
この処理には外部アクセスに必要ない。 -> 外部アクセス「は or が or ...」
主語と述語だけを読む。それだけでも主張がズレないかを調べる。
自分の意見は、S3にあるファイルをサーバーの特定の箇所に置くという処理です。 -> 主語と述語だけを抜き取ると「意見は、処理です」となり、文章の意味が通らない。
ズレる場合、修正する。文を短く切るのが有効な場合があるので、検討する。
段落
ここらへんから日本語として正しいかを調べる必要がなくなってくるので、ある段落が論理構造的に正しいかを調べる。 あと、正直好みもある気がするからなんとアドバイスしてよいか悩ましい...。
段落の結論を述べている一文を探す。ない場合、作る。ある場合、それが1、2文目に入っていなければ移す。 2文目でも良い理由は、たとえば問いかけから始まったり、前の段落を受けての1文で始まったりする場合が考えられるから。 (というか本来は何文目でもいいはずだが、慣れないうちから変な場所に結論を書くのは筋が悪いと思う。)
次に、段落に見出しがある場合は、見出しだけを読んでみる。見出しだけを読んでその段落の主張が分かるか調べる。 わからない場合、わかるように書き直す。
## 自分の意見 自分の意見は、今回はS3のPUTイベントを使って処理を行うべきだと考えています。 ========================== ## S3のPUTイベント通知を使うべき 自分の意見は...
文と文のつながりが破綻していないか調べる。 具体的には、ある文の主張と次の文の主張を比較して、その関係を表すのに適切な接続詞を使ったり使わなかったりする。
案としては、S3のPUTイベントを使うことが考えられます。さらに、バッチ処理で実装することも考えられます。 -> 2つの文は内容は案の列挙。しかし接続詞の「さらに」は前の文に詳しい説明を追加する時に使う。よって不適。
また、段落の主張と、段落に含まれる文リストを比較して十分な論拠を示せているか調べる。 具体的には、今まで出会った中で一番意地悪な質問をする人を脳内でエミュレートしてその人にツッコませる。 ロジックツリーを書いても良いけど、どちらにせよセルフツッコみは必要。
文章
段落に対して行ったチェックを文章に対しても行う。
文章の結論を述べている一文を探す。ない場合、作る。ある場合、それが最初に書いていなければ移す。
文章には普通見出しがあるので、なければ作る。ある場合、見出しだけを読んでみる。見出しだけを読んでその文章の主張が分かるか調べる。 あるいは文章の見出しなら、主張ではなく目的がわかるだけでも良い気がする。 たとえば、以下の見出しはどちらでも良い気がする。
# ○○処理の自動化の実装方針を決める ========================== # ○○処理の自動化をS3のPUTイベント通知をつかって実装したい
段落と段落のつながりが破綻していないか調べる。 こちらは段落内の文のチェックと違って、前後のつながりというよりは論理構成が正しいかを確認する。 具体的には、まず段落の見出しだけを読む。それを読んだだけで大筋は納得できるか調べる。
まとめ
まとめてみた。 文章の論理構造が正しいかのチェック方法を、まだうまいこと明文化できない。自分でもうまいことできてないんだろうな。