SlideShare a Scribd company logo
1 of 31
Elixir入門 第6回
Elixirは try…catchを書かない
例外処理から耐障害性へのパラダイムシフト~
2017/08/17 ver0.5作成
2017/08/23 ver0.9作成
1
1. 例外処理から耐障害性へのシフト
2. try…catchからどう変わるのか?
3. スーパーバイザのプロセス監視、復旧
4. Phoenixから学ぶ準正常系
5. 耐障害性のための構成と復旧戦略
6. パターンマッチと耐障害性へのシフト
7. 「耐障害性プログラミング」にようこそ
目次
2
1.例外処理から耐障害性へのシフト
3
1.例外処理から耐障害性へのシフト
C++やJava、その他、多くのプログラミング言語では、「例外」を
扱うために、try…catchと例外ハンドラのセットで対応します
その中には、「プログラムのバグ」のような、人間が想定し切れない
ような対象も含める必要があります
このように例外処理は、本来のメイン処理で無いハンドラを多数
想定・準備する労力がかかる上、想定外には対応し切れない、
脆弱性を持つアプローチです (ハンドラ自体のバグにも弱い)
一方、Elixirでは、「想定外の発生は仕方無いので、クリーンに
落とし、復旧する」ことに着目した、「耐障害性」を備えています
Elixirにおける、耐障害性のデザインや様式を学ぶことで、障害
対応・例外処理に関するパラダイムシフトを体験できます
4
2.try…catchからどう変わるのか?
5
ログアラータ
従来のプログラム
2.try…catchからどう変わるのか?
try…catchによる例外処理は、「本体処理」をtry~で囲み、
例外発生時は、各catchで捕まえ、例外ハンドラを起動します
一方、Elixirでは、本体処理には手を加えず、「スーパーバイザ」
と呼ばれる監視プログラムを別系で配備します
try
本体処理
例外ハンドラ群
catch①
例外ハンドラ①
catch②
例外ハンドラ②
Elixirプログラム
本体処理
スーパーバイザ
(プロセス監視)
復旧戦略
ダウン
監視
ダウンしたら
再起動
アラート
通知
ログ
監視
6
2.try…catchからどう変わるのか?
監視プログラムからの復旧戦略の代表として「プロセス再起動」が
ありますが、プロセス起動が軽量なElixirだから実現可能という、
プログラミング言語の特性が大きく寄与しています
(関数型言語のイミュータブルな特性も、この実現に貢献します)
・本体処理と例外処理を1つ
のコードにまとめられる
※これは分離できない、という
デメリットでもある
メリット デメリット
Elixir
耐障害性
例外処理
・メモリリークを作り込みやすい
・不整合を作り込みやすい
・プロセスを再起動する設計が
考慮から漏れる可能性がある
・プロセス再起動で全てが解決
できるとは限らない
※とはいえ、プロセス再起動の
設計は例外処理でも本当
は必要
・障害対応を本体処理から
分離できる
・メモリリークや不整合を解消
できる構造
・プロセス再起動を予め設計
7
従来のプログラム
2.try…catchからどう変わるのか?
ちなみに、try…catchによる例外処理をしているプログラムでも、
外部の監視系を導入していれば、Elixirのスーパーバイザと同様
の構築にあたりますが、「例外処理と監視系が障害監視の役割
を重複していた」というケースが実態でしょう (もしくは、プロセスの
再起動が考慮されていなかった、というケースもあり得ます)
try
本体処理
例外ハンドラ群
catch
例外ハンドラ
(外部の監視系)
アラート
ダウン
監視
ダウンしたら
再起動
復旧戦略
通知
8
3.スーパーバイザのプロセス監視、復旧
9
3.スーパーバイザのプロセス監視、復旧
プロセス監視、再起動の例として、「ファイルを読み込み、内容を
返す」という簡単なサーバプログラムを使って説明します
defmodule Pass do
# サーバ
def cat_server() do
receive do
{ sender_pid, path } ->
{ :ok, result } = File.read( path )
send( sender_pid, { true, result } )
end
cat_server()
end
# サーバプロセス起動
def start_cat_server() do
pid = spawn( Pass, :cat_server, [] )
:global.register_name( :cat, pid )
end
# サーバを呼び出すクライアント
def cd( path ) do
send( :global.whereis_name( :cat ), { self(), path } )
listen()
end
end
lib/pass.ex ※Elixir入門 第2回「PC間で通信するアプリをサクっと書いてみる」の例と同じコードです
10
3.スーパーバイザのプロセス監視、復旧
まず、「GenServer」という汎用モジュールを使って書き直します
(サーバとクライアントの書き分けや起動コードが不要になります)
呼び出し方は以下のように変わりますが、実行結果は同じです
defmodule PassGenServer do
use GenServer
def start_link() do
{ :ok, pid } = GenServer.start_link( __MODULE__, "" )
IO.puts( "--- PassGenServer.start_link() PID=#{inspect pid} ---" )
{ :ok, pid }
end
def handle_call( { :cat, path }, _from, _state ) do
{ :ok, result } = File.read( path )
{ :reply, result, "" }
end
end
lib/pass_genserver.ex
iex> { :ok, pid } = GenServer.start_link( PassGenServer, "" )
{:ok, #PID<0.211.0>}
iex> GenServer.call( pid, { :cat, "a.txt" } )
"I'm a.txt"
11
3.スーパーバイザのプロセス監視、復旧
このサーバにおける「想定外」として、以下のようなパターンがあり
ますが、ここでは、存在しないファイルを指定した例を行います
 異常系・・・存在しないファイルを指定、読込権限無、等
 バグ・・・ファイル名が文字列で無い、長過ぎる、等
例外が発生し、サーバプロセスがダウンします
iex> GenServer.call( pid, { :cat, "b.txt" } )
** (EXIT from #PID<0.206.0>) an exception was raised:
** (MatchError) no match of right hand side value: {:error, :enoent}
(node1) lib/pass_genserver.ex:10: PassGenServer.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
14:31:55.520 [error] GenServer #PID<0.211.0> terminating
** (MatchError) no match of right hand side value: {:error, :enoent}
(node1) lib/pass_genserver.ex:10: PassGenServer.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:cat, "b.txt"}
12
3.スーパーバイザのプロセス監視、復旧
サーバプロセスがダウンした後は、存在するファイルを指定しても、
エラーとなります
再度サーバ起動してやり直すと、今度は正常に返します
この流れをプログラム化することで、復旧処理を自動化することが、
「スーパーバイザ」の役割になります
iex> GenServer.call( pid, { :cat, "a.txt" } )
warning: variable "pid" does not exist and is being expanded to "pid()", please use
parentheses to remove the ambiguity or change the variable name
iex:1
** (CompileError) iex:1: undefined function pid/0
(stdlib) lists.erl:1354: :lists.mapfoldl/3
iex> { :ok, pid } = GenServer.start_link( PassGenServer, "" )
iex> GenServer.call( pid, { :cat, "a.txt" } )
"I'm a.txt"
13
3.スーパーバイザのプロセス監視、復旧
スーパーバイザのコードは、以下の通りです
たった、これだけのコードを追加するだけで、プロセスダウン監視と
プロセスダウン後の再起動が実現されることは、驚異的です
例外処理で、同等の処理を書くことは、不可能に限りなく近く、
また自前の監視系を作るのも、骨が折れる作業です
Elixirは、この機能が標準装備されており、非常にお手軽です
import Supervisor.Spec
defmodule PassSupervisor do
def start_link() do
servers = [ worker( PassGenServer, [ 0, [ name: :server_process ] ] ) ]
Supervisor.start_link( servers, strategy: :one_for_one )
end
end
lib/pass_supervisor.ex
14
3.スーパーバイザのプロセス監視、復旧
スーパーバイザを起動します
GenServerプロセス (PID=<0.190.0>) が起動され、監視
するスーパーバイザプロセス (PID=<0.189.0>) が起動され
ていることが確認できます
これまで、PIDを指定してGenServerを呼んでいましたが、スー
パーバイザ経由でのGenServer起動では、PIDを取得すること
ができないため、「:server_process」というプロセス名を付与
しており、プロセス名で呼び出しが可能です
iex> PassSupervisor.start_link()
--- PassGenServer.start_link() PID=#PID<0.190.0> ---
{:ok, #PID<0.189.0>}
iex> GenServer.call( :server_process, { :cat, "a.txt" } )
"I'm a.txt"
15
3.スーパーバイザのプロセス監視、復旧
では、プロセスダウン監視とプロセス再起動を試してみましょう
ログ出力順が逆転していますが、例外が発生し、GenServerが
ダウンしていますが、新たなGenServerが自動起動しています
iex> GenServer.call( :server_process, { :cat, "b.txt" } )
--- PassGenServer.start_link() PID=#PID<0.197.0> ---
** (exit) exited in: GenServer.call(:server_process, {:cat, "b.txt"}, 5000)
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, :enoent}
(node1) lib/pass_genserver.ex:16: PassGenServer.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
(elixir) lib/gen_server.ex:774: GenServer.call/3
iex(4)>
15:22:39.965 [error] GenServer :server_process terminating
** (MatchError) no match of right hand side value: {:error, :enoent}
(node1) lib/pass_genserver.ex:16: PassGenServer.handle_call/3
(stdlib) gen_server.erl:615: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:647: :gen_server.handle_msg/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:cat, "b.txt"}
State: ""
16
3.スーパーバイザのプロセス監視、復旧
本当に再起動できているか確認します
問題無く、再起動できていることが確認できました
このように、スーパーバイザを使うと、とても手軽に、プロセス監視
と再起動を組み込むことができます
ここで気になるのが、プロセスを再起動しても済まないケース…
つまり「準正常系」をどう扱うか、だと思います
この例として、Phoenixのような、エラー時でもレスポンスする
必要があるケースについて、次章で見ていきます
iex> GenServer.call( :server_process, { :cat, "a.txt" } )
"I'm a.txt"
17
4.Phoenixから学ぶ準正常系
18
4.Phoenixから学ぶ準正常系
ここまでの障害対応は、「異常系」「バグ」の2パターンのみでした
一方で、PhoenixのようなWebアプリでは、404エラーのような、
レスポンスを返すエラーがあり、これは「準正常系」と呼ばれます
19
4.Phoenixから学ぶ準正常系
準正常系は、異常系やバグと異なり、発生が想定可能なため、
try…catchでのエラーハンドリングを作り込むこととなります
Phoenixで、404エラーのような準正常系のエラーハンドリングが、
どのように実現されているか見てみましょう
tryの中の本体処理で、例外が発生した場合、catch中にある、
エラーレンダラーが呼び出され、エラーページが表示されます
defmodule Phoenix.Endpoint do
…
def call(conn, opts) do
…
try do
super(conn, opts)
catch
kind, reason ->
Phoenix.Endpoint.RenderErrors.__catch__(conn, kind, reason, @phoenix_render_errors)
end
end
…
deps/phoenix/lib/phoenix/endpoint.ex
20
4.Phoenixから学ぶ準正常系
ここまでをまとめると、障害対応において大事なことは、「異常系」
「バグ」「準正常系」の3種類を、「明確に区別する」ということです
「異常系」「バグ」の場合は、想定ができないため、try…catch
でのエラーハンドリングは書かず、プロセスをダウンさせ、再起動で
クリーンナップする方向で対応します
一方、「準正常系」は、想定可能なため、try…catchでエラー
ハンドリングを作り込み、暗黙のプロセスダウン/再起動には
任せません
万全と、「try…catchは普通に書くものだ」と自動思考すること
で、この区別が不明確となるような事態を、Elixirは避けられる
構造を持っており、自然と耐障害性が実現されます
21
5.耐障害性のための構成と復旧戦略
22
5.耐障害性のための構成と復旧戦略
ここまでは、単品かつデータも持たない単純なプロセスでの復旧を
見てきましたが、複数プロセスで、共通のデータを保持する場合
には、以下のような構成が必要となってきます
共通データ
保持プロセス
スーパーバイザ
監視
本体処理①
プロセス
監視
本体処理②
プロセス
監視
23
5.耐障害性のための構成と復旧戦略
更に、本体処理自体が、複数のプロセスで構成される場合は、
サブのスーパーバイザを作り、そのプロセスグループの中で再起動
を制御できます
共通データ
保持プロセス
スーパーバイザ
監視
本体処理①
プロセス
監視
本体処理②-1
プロセス
監視
本体処理②用
スーパーバイザ
本体処理②-2
プロセス
監視 監視
24
5.耐障害性のための構成と復旧戦略
スーパーバイザから、スーパーバイザを起動するコードは、以下の
ようになります
通常のサーバを起動するコードと、ほぼ変わりません
import Supervisor.Spec
defmodule PassSubSupervisor do
def start_link() do
servers = [ worker( PassGenServer, [ 0, [ name: :server_process ] ] ) ]
Supervisor.start_link( servers, strategy: :one_for_one )
end
end
lib/pass_sub_supervisor.ex
import Supervisor.Spec
defmodule PassSupervisor do
def start_link() do
servers = [ supervisor( PassSubSupervisor, [ 0, [ name: :ssv_process ] ] ) ]
Supervisor.start_link( servers, strategy: :one_for_one )
end
end
lib/pass_supervisor.ex
25
5.耐障害性のための構成と復旧戦略
「復旧戦略」が、何種類か選べます (代表2つを紹介)
 one_for_one ・・・ 1プロセス落ちたら1プロセス再起動
 one_for_all ・・・ 1プロセス落ちたら配下を全再起動
共通データ
保持プロセス
スーパーバイザ
監視
本体処理①
プロセス
監視
本体処理②-1
プロセス
監視
本体処理②用
スーパーバイザ
本体処理②-2
プロセス
監視 監視
26
6.パターンマッチと耐障害性へのシフト
27
6.パターンマッチと耐障害性へのシフト
「想定外」のうち、バグの例として、「ファイル名が文字列で無い」
「長過ぎる」といった、いわゆる「バリデーションチェック」に相当する
ものを紹介しました
他の言語であれば、関数に入った後に、バリデーションチェックを
行いますが、Elixirでは、「パターンマッチ」による、関数呼出前の
チェックが行えます
この特徴を活用すると、想定外に対するバリデーションチェックの
開発をスキップし、本体処理のコーディングにより専念することが
可能となります
「try…catchの煩雑さ」と「バリデーションチェックの煩雑さ」が、
コードから無くなり、シンプルな本質のみのコードという世界観です
28
7.「耐障害性プログラミング」にようこそ
29
7.「耐障害性プログラミング」にようこそ
今回は、try…catchに変わる障害対応として、スーパーバイザ
を使ったプロセス監視と再起動についてご説明しました
Elixirの耐障害性プログラミングが「そこまで難しく無いかも?」と
思っていただけたら、この入門としては大成功です
本体処理に例外処理を混ぜず、障害対応を分離し、想定外が
発生した際はプロセス再起動する世界は、これまで親しんだプロ
グラミングの概念と、大きく異なるコンセプトでは無かったでしょうか
このシンプルで強力な役割の分離により、プログラムの設計という
ものが根底から改善されます
この新たなパラダイムを活かし、仕事でも趣味でも、プログラミング
ライフをエンジョイしてください!
30
ご清聴ありがとうございます

More Related Content

What's hot

ダブル配列の実装方法
ダブル配列の実装方法ダブル配列の実装方法
ダブル配列の実装方法
Higashiyama Masahiko
 
TDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめ
TDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめTDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめ
TDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめ
Kei Sawada
 

What's hot (20)

MediaPipeを使ったARアプリ開発事例 ~カメラをかざして家䛾中で売れるも䛾を探そう~
MediaPipeを使ったARアプリ開発事例 ~カメラをかざして家䛾中で売れるも䛾を探そう~MediaPipeを使ったARアプリ開発事例 ~カメラをかざして家䛾中で売れるも䛾を探そう~
MediaPipeを使ったARアプリ開発事例 ~カメラをかざして家䛾中で売れるも䛾を探そう~
 
Python x ハードウェアの可能性
Python x ハードウェアの可能性Python x ハードウェアの可能性
Python x ハードウェアの可能性
 
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
 
JenkinsとDockerって何が良いの? 〜言うてるオレもわからんわ〜 #jenkinsstudy
JenkinsとDockerって何が良いの? 〜言うてるオレもわからんわ〜 #jenkinsstudyJenkinsとDockerって何が良いの? 〜言うてるオレもわからんわ〜 #jenkinsstudy
JenkinsとDockerって何が良いの? 〜言うてるオレもわからんわ〜 #jenkinsstudy
 
コンテナネットワーキング(CNI)最前線
コンテナネットワーキング(CNI)最前線コンテナネットワーキング(CNI)最前線
コンテナネットワーキング(CNI)最前線
 
DockerとPodmanの比較
DockerとPodmanの比較DockerとPodmanの比較
DockerとPodmanの比較
 
TLS 1.3 と 0-RTT のこわ〜い話
TLS 1.3 と 0-RTT のこわ〜い話TLS 1.3 と 0-RTT のこわ〜い話
TLS 1.3 と 0-RTT のこわ〜い話
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 
Rpn and forth 超入門
Rpn and forth 超入門Rpn and forth 超入門
Rpn and forth 超入門
 
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
 
数学カフェ 確率・統計・機械学習回 「速習 確率・統計」
数学カフェ 確率・統計・機械学習回 「速習 確率・統計」数学カフェ 確率・統計・機械学習回 「速習 確率・統計」
数学カフェ 確率・統計・機械学習回 「速習 確率・統計」
 
複数サービスを使う業務の自動化にはRPA×Node-RED構成がおすすめ/Node-RED Desktop紹介
複数サービスを使う業務の自動化にはRPA×Node-RED構成がおすすめ/Node-RED Desktop紹介複数サービスを使う業務の自動化にはRPA×Node-RED構成がおすすめ/Node-RED Desktop紹介
複数サービスを使う業務の自動化にはRPA×Node-RED構成がおすすめ/Node-RED Desktop紹介
 
Rust で RTOS を考える
Rust で RTOS を考えるRust で RTOS を考える
Rust で RTOS を考える
 
インフラエンジニアのためのRancherを使ったDocker運用入門
インフラエンジニアのためのRancherを使ったDocker運用入門インフラエンジニアのためのRancherを使ったDocker運用入門
インフラエンジニアのためのRancherを使ったDocker運用入門
 
DPDKによる高速コンテナネットワーキング
DPDKによる高速コンテナネットワーキングDPDKによる高速コンテナネットワーキング
DPDKによる高速コンテナネットワーキング
 
デプスセンサとその応用
デプスセンサとその応用デプスセンサとその応用
デプスセンサとその応用
 
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
つながるロボット 〜分散協調ロボットの開発を加速化するROSの紹介〜
 
ダブル配列の実装方法
ダブル配列の実装方法ダブル配列の実装方法
ダブル配列の実装方法
 
TDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめ
TDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめTDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめ
TDDを実践してわかったTDDつまづくあるあると自分なりの乗り越え方まとめ
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 

Similar to Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」

東京Node学園#8 Let It Crash!?
東京Node学園#8 Let It Crash!?東京Node学園#8 Let It Crash!?
東京Node学園#8 Let It Crash!?
koichik
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7
Tetsuya Morimoto
 
Error handling in Erlang and Scala
Error handling in Erlang and ScalaError handling in Erlang and Scala
Error handling in Erlang and Scala
Masahito Ikuta
 
LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)
Kazuko Itoda
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
Masanori Oobayashi
 

Similar to Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」 (20)

東京Node学園#8 Let It Crash!?
東京Node学園#8 Let It Crash!?東京Node学園#8 Let It Crash!?
東京Node学園#8 Let It Crash!?
 
エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7エキ Py 読書会02 2010/9/7
エキ Py 読書会02 2010/9/7
 
エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半エキ Py 読書会02 2章後半
エキ Py 読書会02 2章後半
 
Error handling in Erlang and Scala
Error handling in Erlang and ScalaError handling in Erlang and Scala
Error handling in Erlang and Scala
 
Kanazawa.js.Next
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Next
 
Rust Error Handling
Rust Error HandlingRust Error Handling
Rust Error Handling
 
はじめてのCodeIgniter
はじめてのCodeIgniterはじめてのCodeIgniter
はじめてのCodeIgniter
 
Java/Androidセキュアコーディング
Java/AndroidセキュアコーディングJava/Androidセキュアコーディング
Java/Androidセキュアコーディング
 
JavaScript基礎勉強会
JavaScript基礎勉強会JavaScript基礎勉強会
JavaScript基礎勉強会
 
[db tech showcase Tokyo 2014] B26: PostgreSQLを拡張してみよう by SRA OSS, Inc. 日本支社 高塚遥
[db tech showcase Tokyo 2014] B26: PostgreSQLを拡張してみよう  by SRA OSS, Inc. 日本支社 高塚遥[db tech showcase Tokyo 2014] B26: PostgreSQLを拡張してみよう  by SRA OSS, Inc. 日本支社 高塚遥
[db tech showcase Tokyo 2014] B26: PostgreSQLを拡張してみよう by SRA OSS, Inc. 日本支社 高塚遥
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
LLVM overview 20110122
LLVM overview 20110122LLVM overview 20110122
LLVM overview 20110122
 
実践 NestJS
実践 NestJS実践 NestJS
実践 NestJS
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)
 
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
【SQiP2014】システム操作インターフェイス最適化によるテスト自動化ROI向上
 
Serfが面白いと俺の中で話題にwwwwww 【改訂版】
Serfが面白いと俺の中で話題にwwwwww 【改訂版】Serfが面白いと俺の中で話題にwwwwww 【改訂版】
Serfが面白いと俺の中で話題にwwwwww 【改訂版】
 
Rails3.2ってどう変わるの?
Rails3.2ってどう変わるの?Rails3.2ってどう変わるの?
Rails3.2ってどう変わるの?
 
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのかJavaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
Javaの進化にともなう運用性の向上はシステム設計にどういう変化をもたらすのか
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
 

More from fukuoka.ex

More from fukuoka.ex (12)

AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
AI入門「第4回:ディープラーニングの中身を覗いて、育ちを観察する」
 
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
【macOSにも対応】AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」
 
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
【LT版】Elixir入門「第7回:Python/KerasをElixirから繋いでアレコレする」
 
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
Elixir入門「第3回:Phoenix 1.3で高速webアプリ & REST APIアプリをサクッと書いてみる」
 
Elixir入門「第5回:Visualixirで見るマルチプロセス」
Elixir入門「第5回:Visualixirで見るマルチプロセス」Elixir入門「第5回:Visualixirで見るマルチプロセス」
Elixir入門「第5回:Visualixirで見るマルチプロセス」
 
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版ありますAI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
AI入門「第3回:数学が苦手でも作って使えるKerasディープラーニング」【旧版】※新版あります
 
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
重力プログラミング入門「第1回:地球の重力下で人工衛星を公転軌道に乗せる」
 
AI入門「第1回:AIの歴史とTensorFlow」
AI入門「第1回:AIの歴史とTensorFlow」AI入門「第1回:AIの歴史とTensorFlow」
AI入門「第1回:AIの歴史とTensorFlow」
 
やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介
 
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
AI入門「第2回:Scala/Spark/Mahoutでレコメンドエンジンを作る」
 
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版ありますElixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
Elixir入門「第1回:パターンマッチ&パイプでJSONパースアプリをサクっと書いてみる」【旧版】※新版あります
 
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版ありますElixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
Elixir入門「第3回:Phoenix 1.2で高速Webアプリ & REST APIをサクッと書いてみる」【旧版】※新版あります
 

Elixir入門「第6回:Elixirはtry…catchを書かない~障害対応のパラダイムシフト~」