銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

当ブログではアフィリエイト広告を利用しています

【徳丸本勉強メモ】クッキー出力にまつわる脆弱性

はじめに

最近、会社で徳丸本(体系的に学ぶ 安全なWebアプリケーションの作り方 第2版)の勉強会が始まりました。

毎週持ち回りで発表していく形式で、僕の発表するパート(クッキー出力にまつわる脆弱性)についてまとめたので、ブログにも載せようと思います。

会社での勉強会の雰囲気などはこちらの記事をご覧ください。

www.wantedly.com

ちなみに、徳丸本というのはWebアプリケーションのセキュリティに関するめちゃくちゃ有名な本です。 

f:id:ysk_pro:20180924094455j:plain

サマリー

- Webアプリケーションではクッキーによるセッション管理が広く使われている

- クッキーにまつわる脆弱性

  ① クッキーを利用すべきでない目的でクッキーを使っている
  【対策】クッキーはセッションIDの保管場所として利用すべきで、それ以外のデータをクッキーに保存しない方が良い

  ② クッキーの出力時に脆弱性が発生する(クッキーのセキュア属性不備)
  【対策】HTTPS通信を用いるアプリケーションのクッキーにはセキュア属性を指定する

 

クッキーの不適切な利用について

Webアプリケーションで、ページをまたがる情報を保存する方法としては、セッション管理機構が用いられる。

一般的にセッション管理機構は、セッションIDのみをクッキーに保存して、データ自体はWebサーバーのメモリやファイル、データベースなどに保存している。

クッキーはアプリケーション利用者によって書き換えができるため、クッキーに保存すべきでないデータをクッキーに保存すると、脆弱性が発生する場合がある。

 

クッキーに保存すべきでない情報とは?

ユーザIDや権限情報

これらは書き換えられると困る情報である。

これらの情報をクッキーに保存していると、権限外の操作や情報閲覧ができてしまう場合がある。

クッキーに保存すべきでない情報以外であっても、一般的にクッキーにデータを保存しない方が良い

 

クッキーよりセッション変数を使うべき理由

セッション変数の方が便利で安全に使用できるため、通常はセッション変数を利用すべきである。

ただし、クッキーで実現できてセッション変数で実現できないのは、情報の寿命の制御と、異なるサーバーとの情報共有のみであり、これらが必要な場合はクッキーを利用する。

異なるサーバーでの情報共有のクッキーの使用例としては、ログイン画面の「ログイン画面を保持する」という機能がある。この機能はクッキーによりログイン状態が保持される。この時、クッキーに保存される情報はトークンという乱数で、IDやパスワードをクッキーに保存するわけではない。

クッキーにデータを保存する方法とセッション変数を使う方法の比較は下表の通り。

f:id:ysk_pro:20180924090256p:plain

(徳丸本 p.255 より抜粋)
 

クッキーのセキュア属性不備による脆弱性

クッキーにはSecureという属性があり、これを指定したクッキーはHTTPSの場合のみブラウザからサーバーに送信される

クッキーにはセッションIDなどセキュリティ上重要な情報が格納されている場合が多いので、クッキーが盗聴されると成りすましの被害に直結する

クッキーのセキュア属性不備への対策は、クッキーのセキュア属性を設定することである。

 

脆弱性が生まれる原因(クッキーにセキュア属性をつけない原因)

  • 開発者がセキュア属性について知らないケース
  • セキュア属性をつけるとアプリケーションが動かなくなるケース
  • HTTPとHTTPSが混在するWebアプリケーションの場合、セッションIDを保持するクッキーにセキュア属性を設定することは困難である。セッションIDのクッキーにセキュア属性をつけると、HTTPのページではセッションIDのクッキーが受け取れないため、セッション管理機構が使えなくなってしまう。サイト全体をHTTPSにするのが難しい場合、トークンを用いて対策する方法もある。
 

覚えておくべきこと

  • クッキーはセッションIDの保管場所として利用すべきで、それ以外のデータをクッキーに保存しない方が良い
  • HTTPS通信を用いるアプリケーションのクッキーにはセキュア属性を指定する

 

おわりに

この本は一度通して読んでいるのですが、勉強会で自分が発表するために読み直してまとめると、より理解が深まりました

会社で勉強会を行なっているように、実務ではセキュリティの知識は必須なので、セキュリティに関して自信が無いという方は是非こちら読んでみることをおすすめしますー! 

 

 

【元銀行員の僕が教える】銀行のちょっと面白くて、役に立つこと 〜信用創造・ペイオフ編〜

こんにちは。ゆうすけです。

いきなりですが、実は僕、今はエンジニアをしていますが、新卒から4年間は銀行で中小企業から上場企業までを相手に、融資の提案などをしていました。

f:id:ysk_pro:20180915104907j:plain

1. この記事を書いたきっかけ

僕が今勤めている会社では、毎週金曜に、参加自由・発表自由・テーマ自由のゆるーいLT会があります。

みんな色んなテーマのことをLTしてて面白い、、!

 

そこで銀行に勤めていた経験から、「銀行について知ってたら面白いこと、役に立つこと」というテーマでLTしてみたら、みんなが興味示してくれたので、ブログにもしちゃおうかな〜と思いました。

シリーズ化も考えてますーー。

 

2つのことについて書いていきます。

 

2. 信用創造

f:id:ysk_pro:20180915090759p:plain

1つ目は信用創造についてです。

これは社会に対して銀行が担っている、重要な役割の中の1つです。

信用創造を一言で言えば、銀行がお金を貸せば貸すほど、世の中にお金が増えていく仕組み、となります。

ちょっと意味がわかりませんよね(笑)

次の図で解説しています。

f:id:ysk_pro:20180915090820p:plain

<図中の取引の説明>

① 銀行が100万円持っています

② 銀行はその100万円を会社Aに融資します

③ 会社Aはその100万円全額をすぐに使う予定はないので、90万円を銀行に預金します

④ 銀行はその90万円を会社Bに融資します

⑤ 会社Bも会社Aと同様に、全額をすぐに使う予定はないので、80万円を銀行に預金します

 

すると、、、会社A・会社B・銀行が使うことができるお金の合計は270万円(図中の赤字部分)になっています、、、!

銀行がお金を貸しただけで世の中のお金が増えましたよね。

ざっくりとですがこれが信用創造で、銀行が社会に果たしている重要な役割の1つなのです。

 

3. ペイオフ

f:id:ysk_pro:20180915090847p:plain

2つ目は知っておくと役立つことです。

最近、マイナス金利などで銀行の経営が危ないっていうニュース多いですよね〜。

銀行がもし、もし潰れてしまったら、預けている預金はどうなるんでしょうか、、、?

ちょっと心配ではないですか? 

 

f:id:ysk_pro:20180915090856p:plain

実は、銀行が潰れても、1人1銀行につき、元本1,000万円とその利息については、預金保険制度(ペイオフ)によって補償されます

なので、預金が1,000万円以上ある方は、銀行を分けて預金しておくとベターです。

 

 

ちなみに、信用創造の2枚目の図と、ペイオフの2枚目の図は、僕が夜な夜な資料を作っていたら、センスの無さに見かねて妻が綺麗にしてくれました。

めちゃ見やすい、、、すごい。

 

4. おわりに

いかがだったでしょうか?

当たり前のことばかりですか??

僕は信用創造を初めて知った時は、おおー、面白い、銀行すごいな〜と思いました。

 

そんな僕が銀行を辞めた理由・ITエンジニアになった理由についてはこちらのnoteに詳細を書き、多くの反響をいただいておりますので、もしよろしければ合わせて読んでみてください!

note.mu

また、最近何かと話題になる「個人型確定拠出年金iDeCo / イデコ)」について図を使って分かりやすくまとめたのでこちらの記事も是非合わせてご覧ください。

ysk-pro.hatenablog.com

お読みいただきありがとうございました。

【技術書メモ】現場で使えるMySQL 〜毎週アウトプットチャレンジ⑧〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第8弾ですー!

今回は、現場で使えるMySQL を読んでまとめました。

MySQL現場で使うための知識を、分かりやすく解説している技術書です。

現場で使える MySQL (DB Magazine SELECTION)

現場で使える MySQL (DB Magazine SELECTION)

 

f:id:ysk_pro:20180908194233j:plain

Chapter1 MySQLの概要と環境構築

  • データベース領域:インスタンスと1対1に対応した、データベースの物理領域。1つのデータベース領域の中に複数のデータベースが格納される
  • 権限データベース:mysqlという名前のデータベース。インスタンスへ接続するためのユーザー情報や、各データベース、テーブルにアクセスするための権限情報が複数のテーブル内に格納されている
  • 初期パラメータファイル:インスタンスの使用メモリやサイズやファイル配置などを決めるためのファイル
  • MySQLユーザー:MySQLインスタンスに接続するためのDBアカウント
 

Chapter2 データ型とSQL

  • データや値の範囲チェックはアプリケーション側の責任であるという考え方に基づいて実装されている。例えば、どのデータ型でも、範囲を超えた値を格納しようとしてもエラーにはならず、削られたり最大値や0に変換されたりするので注意が必要
  • 文字列型で最大長を超える文字を格納しようとした場合、オーバーした部分は削られた上で正常終了する
  • ソートや文字列比較において、デフォルトでは半角英字の大文字/小文字を区別しない
  • 数値型のNUMERIC型は、NUMERIC(p,n)という形で定義され、pは全体の有効桁数、nは小数点以下の有効桁数を意味する。p,nどちらも指定しなかった場合、NUMERIC(10,0)となる
  • 日付/時刻型としては、YEAR/DATE/TIME/DATETIME/TIMESTAMPの5種類がある
  • 列挙型とは、あらかじめ復すの文字列値を定義しておいて、その中からしか選択できないようにするためのデータ型で、ENUMとSETの2種類がある。ENUM型は定義値の中から1つのみ選択できて、SET型は複数選択できる
 

Chapter3 テーブル定義

  • 主なストレージエンジンとその特徴
  • 整合性制約
    • 主キー制約:制約対象列にNULL値を入れないことと、値が重複しないことを保証する。これにより、制約対象列の値からテーブル内の行を一意に識別できる
    • 一意キー制約:制約対象列の値が重複しないことを保証する。NULL値は格納でき、NULL値同士は異なる値であると見なされる
    • 参照整合性制約(外部キー制約):子テーブルの制約対象列の値が、親テーブルの参照キーに含まれていることを保証するもので、子テーブルに定義する。利用するためには、親テーブル、子テーブルともInnoDBである必要がある
  • シーケンス:連続的な整数値を生成するオブジェクト。シーケンスから得られる数値のことをシーケンス番号、連番などと呼ぶ。一般的に、同一のシーケンスから得られるシーケンス番号は重複しないため、テーブルの主キーや一意キーとして使用されることが多い
 

Chapter4 トランザクション

  • 自動コミット機能:この機能を有効にするか無効にするかによって、トランザクションの開始/終了の方法が変化する
    • 有効にした場合:トランザクションは単一のSQL文を実行した時点で自動的に、または、START TRANSACTION文によって明示的に開始する。START TRANSACTION文を実行していない場合は、単一のSQL文が実行された時点で自動的にコミットし、ロールバックできない。一方、START TRANSACTION文を実行している場合は、単一のSQL文が終了しただけではコミットせず、COMMIT文を実行した時点ではじめてコミットする。また、ROLLBACK文を実行するとロールバックする
    • 無効にした場合:トランザクションは、SQL文の実行によって暗黙的に、またはSTART TRANSACTION文で明示的に開始する。いずれの場合も自動的にコミットしない。COMMIT文を実行した時点でコミットし、ROLLBACK文を実行した時点でロールバックする
  • デフォルトでは自動コミット機能が有効となっている
  • ロックとは、複数のトランザクション間での排他制御を実現するための仕組み。InnoDBでは、テーブルの行(レコード)単位でロックをかけられる。
  • フルスキャンはすべての行にロックがかかってしまうため、インデックス検索させるべきところにはきちんとインデックスを作成すべき
  • デッドロックは即座に検出される
 

Chapter6 日本語処理

  • クライアントとサーバーの文字コードをすべてutf8に統一できる環境ならば問題はないが、そうでなければ様々な注意事項が存在する
 

Chapter8 アーキテクチャ/ファイル構成

  • インスタンスMySQLサーバー側で動作するプロセス/スレッド群と、それらが使用するメモリの総称
  • MySQLは、複数のクライアント側プロセスと1つのサーバー側プロセス「mysqld」で構成される。多くのRDBMSがマルチプロセスで動作するのとは対照的に、MySQLのサーバー側はマルチスレッドで動作する
  • プロセスとは、UNIXコマンドで言えばcatやlsといった個々のプログラムの実行単位である。OS上の各プロセスには、それぞれの固有のメモリ空間が割り当てられる。一方スレッドとは、簡単に言えば1つのプロセス内で並行処理を行うためのものである。スレッドはプロセスの内部で生成され、プロセスのメモリ空間を共有する
  • ストレージエンジンはアプリケーション側から隠蔽されている。アプリケーション側から発行するSQL文は、インスタンス側で動作するパーサーと呼ばれるプログラムによって解析され、どのインデックスを使用するか、といった実行計画が作成された上で、はじめて対象のストレージエンジンに処理が渡る。アプリケーションから見ると、ストレージエンジンが変わったとしても、発行するSQLが変わるわけではない
 

Chapter9 ユーザ管理/セキュリティ

  • MySQLにアクセスするにはまず認証を行う。認証とは、アクセス元が本人に間違いないことを確認することで、ユーザ名・アクセス元のホスト名/IPアドレス・パスワードの3つで認証する
  • OSユーザーとは別にMySQLユーザーという概念があり、MySQLインスタンスにアクセスする際に使用する。管理者ユーザーという特別なユーザーもあり、デフォルトではrootという名前になっている。MySQLユーザーは認証や権限管理のために存在する
  • 権限は、グローバル(全体)、データベース、テーブル、列の4種類ごとに設定する
  • 発行されたすべてのSQL文をファイルに記録する機能があるため、監査機能として使うことができる
 

Chapter10 バックアップ/リカバリ(前編)

  • バックアップ方法
    • コールドバックアップ:インスタンスを停止した状態で全体バックアップを取得する方法。したがって、バックアップの最中はインスタンスに対して一切アクセスできない。tarやcpなどのOSコマンドで取得する。
    • オンラインバックアップ:インスタンスを起動した状態でバックアップを取得する方法。
  • バックアップ/リカバリの基本的な流れは、バックアップ→メディア障害発生→リストア→リカバリである。
    • メディア障害とは、ディスクの故障やオペレーションミスなどにより、MySQLの実データが失われる障害のこと
    • リストアとはバックアップの時点まで復旧すること
    • リカバリは障害直前の時点まで復旧すること
 

Chapter11 バックアップ/リカバリ(後編)

  • MySQLのオンラインバックアップでの定番は「mysqldump」。データベース領域全体でも、テーブルやデータベース単位でもバックアップでき、バックアップデータはテキスト形式で、SQL文がそのまま記述される。MySQLインスタンスに接続→バックアップ対象のすべてのテーブルに対しSELECT文を実行し、テキスト形式で出力→すべてのバックアップが終了したら接続を終了、という流れで動作する
 

Chapter12 レプリケーション

  • レプリケーションとは、テーブルなどの各種オブジェクトの複製を他のサーバー上に生成するという技術。レプリケーションによって、負荷分散と可用性の向上を実現できる
  • 1台のマスターに対して更新を行うと、複数のスレーブにも同じ更新結果が反映される。検索は基本的にスレーブに対して行えばよいので、検索の負荷分散になる
  • レプリケーションは、スレーブにバックアップ機としての役割を持たせることによって、バックアップ/リカバリの手段としても利用できる
  • マスターに障害が発生した場合は、スレーブをマスターに昇格させてサービスを継続することで、サービス停止時間を短くすることができる
 

Chapter13 パフォーマンスチューニング(前編)

  • RDBMSのチューニングは単体チューニングとシステムチューニングの2つに大別できる
  • 単体チューニングとは、個々のSQL文の実行性能を改善する作業のことで、具体的にはインデックスの作成やSQL文の修正、アプリケーションロジックの見直しによるSQL発行回数を減らすことが含まれる
  • システムチューニングとは、システム全体の観点から、MySQLの初期化パラメータやOSのカーネルパラメータの設定を行うことが含まれる
  • 単体チューニングでは下記2つの手段を組み合わせる
    • スロークエリログから、実行時間の長いSQLや非効率なフルスキャンを行なっているSQL文の特定
    • 上記SQL文の実行計画をEXPLAIN文で確認し、必要に応じた改善
 

Chapter14 パフォーマンスチューニング(後編)

  • 基本的にデータ型は使用バイト数が少ないデータ型を選ぶことを心がけると良い。そうでないと、ファイルサイズが大きくなるだけでなく、多くのI/Oが発生するため性能面でも悪影響がある
  • SELECT/UPDATE/DELETE文のWHERE句で指定する列に対しては、インデックスを定義することでフルスキャンを防ぐのが一般的である。ただし、インデックスを作ると更新時にオーバーヘッドがかかることに注意する
  • バルクINSERT文とは、1つのSQL文で複数のレコードをまとめてINSERTする構文であり、通常のINSERT文を繰り返すのに比べ、大きな性能向上が図れる
  • テーブルのレコードデータをすべて削除する場合は、「DELETE FROM テーブル名;」よりも、「TRUNCATE TABLE テーブル名;」の方がはるかに高速
 

おわりに

ここまで読んでいただきありがとうございます。

MySQL、とても奥が深いですね、、、!
現場でMySQLを使っている方には特に本書オススメですー!
現場で使える MySQL (DB Magazine SELECTION)

現場で使える MySQL (DB Magazine SELECTION)

 

次もMySQLに関する技術書を読む予定です。

来週も頑張ります!

【技術書メモ】SQL 第2版 ゼロからはじめるデータベース操作 〜毎週アウトプットチャレンジ⑦〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第7弾ですー!

今回は、SQL 第2版 ゼロからはじめるデータベース操作 を読みました。

データベース・SQLについて、とても分かりやすく書かれた入門書です。 

SQL 第2版 ゼロからはじめるデータベース操作

SQL 第2版 ゼロからはじめるデータベース操作

 

f:id:ysk_pro:20180902101951j:plain

第1章 データベースとSQL

  • SQLは、RDBMSに与える命令の種類により、次の3つに分類される
    • DDL(Data Definition Language):データベースやテーブルを作成、削除などをする。(CREATE、DROPなど)
    • DML(Data Manipulation Language):テーブルの行を検索、変更などをする。(SELECT、INSERTなど)
    • DCL(Data Control Language):データベースに対して行った変更を確定、取消などをする。(COMMIT、ROLLBACKなど)
  • データ型
    • CHAR型:文字列を入れる型。CHAR(10)のように、入れることの出来る最長の長さを()で指定する。CHAR型は、固定長文字列という形式でデータが格納され、文字列の長さが最大長に満たない場合は、満たない分を文字の後に半角スペースを入れて埋める。
    • VARCHAR型:CHAR型と同じく文字列を入れる型。違いは、VARCHAR型は可変長文字列という形式で、文字数が最大長に満たない場合も半角スペースで埋めない点。
 

第2章 検索の基本

  • SELECTを使った検索で結果から重複を省く場合は、SELECTの後に「DISTINCT」をつける。DISTINCTを使った場合、NULLも1種類のデータとして扱われ、複数の行にNULLがある場合は、1つにまとめられる。
  • NULLを含んだ計算の結果は、問答無用でNULLになる。NULLを0で割る場合もエラーとならずNULLとなる。
 

第3章 集約と並び替え

  • COUNT関数は基本的にNULLを除外するが、COUNT(*)とすればNULLを含めた全行を数えることができる。
  • COUNT(*)以外の集約関数はNULLを除外して算出する。(0としても扱わない)
  • WHERE句には行に対する条件を書き、HAVING句にはグループに対する条件を書く。どちらにも書くことが出来る条件をWHERE句に書くべき理由は、可読性と実行速度。
  • ORDER BYでのソートキーにNULLが含まれる場合は、先頭か末尾にまとめられる。
  • ORDER BY句はSELECT句よりも実行されるのが後なので、SELECT句でつけた別名を使用できる。
 

第4章 データの更新

  • テーブルからデータを削除する方法として、DELETE文だけでなく、「TRUNCATE」というコマンドがある。TRUNCATEは必ずテーブルを全行削除し、DELETEよりも処理が高速という特徴がある。
  • DBMSトランザクションは、ACID特性と呼ばれる4つの特性がある。
    • 原子性(Atomicity):トランザクションが終わったとき、そこに含まれていた更新処理は、全て実行される or 全て実行されない状態で終わることを保証すること。
    • 一貫性(Consistency):トランザクションに含まれる処理は、データベースにあらかじめ設定された制約を満たすこと。
    • 独立性(Isolation):トランザクション同士が互いに干渉を受けないことを保証すること。トランザクション同士は入れ子になることはない。
    • 永続性(Durability):トランザクションが終了したら、その時点でのデータの状態が保存されることを保証すること。
 

第5章 複雑な問い合わせ

  • ビューとは、テーブルと同じように扱われる。違いは、テーブルの中には実際のデータが保存され、ビューの中にはSELECT文が保存されていること。
  • ビューのメリット
    • データを保存しないため、記憶装置の容量を節約できること。
    • 頻繁に使うSELECT文を、ビューとして保存することで、使い回せること。
  • サブクエリとは使い捨てのビューであり、SELECT文の実行終了後に消去される。
  • スカラ・サブクエリとは、戻り値が単一の値になるサブクエリであり、WHERE句などで使われる。
 

第6章 関数、述語、CASE式

  • 関数
    • ||:文字列連結
    • REPLACE:文字列中のある一部分を、別の文字列に置き換える
    • CURRENT_TIMESTAMP:現在の日時(CURRENT_DATE + CURRENT_TIME)
    • EXTRACT:日付データからその一部分(年や月)を、数値型として切り出す
    • CAST:型変換を行う
    • COALESCE:可変数の引数を取り、最初にNULLでない値を返す。NULLを別の値に変えて扱いたい場合などに使われる。
  • 述語:戻り値が真理値になる関数
    • IS NULL:ある列がNULLの行を選択する場合に、=は使うことができず、IS NULLを使う必要がある。反対にNULL以外の行を選択する場合は、IS NOT NULLを使う。
    • IN:ORの便利な省略形。反対はNOT IN。INは引数にサブクエリを指定する使い方もされる。
    • EXISTS:ある条件に合致するレコードの存在有無を調べる。INによってほぼ代用できる。
  • CASE式:場合分けを記述する時に使用する。ELSE NULLは省略可能であるが、可読性の観点から省略しない方がよい。
 

第7章 集合演算

  • 集合演算子は重複行を排除する。ALLを追加すれば重複行は排除されない。
  • UNION:レコードの足し算を行う。
  • INTERSECT:2つのレコードの共通部分を選択する。
  • EXCEPT:レコードの引き算を行う。
  • 結合(JOIN)は、別のテーブルから列を持ってきて、列を増やす集合演算。UNIONがテーブル同士を行方向(縦方向)に連結するのに対し、結合は列方向(横方向)に連結する。
  • 内部結合(INNER JOIN)は2つのテーブルの両方に存在する情報だけを選択するのに対して、外部結合(OUTER JOIN)はどちらか一方のテーブル(LEFT or RIGHTで指定する)に存在しているならば、そのテーブル情報が欠けることなく出力される。
 

第8章 SQLで高度な処理を行う

  • ウィンドウ関数は、ランキング、連番生成など通常の集約関数ではできない高度な操作を行う
  • GROUPING演算子は、GROUP BY句と集約関数ではできなかった小計・合計を同時に求めることができる

 

おわりに

ここまで読んでいただきありがとうございます。

Railsから入ったりすると、DB・SQLの学習は後回しになりがちですが、大規模なDBを扱う実務ではDBの知識はめちゃくちゃ重要です。

本書は基本的なところから書かれているので、とても分かりやすくスッと読むことができ他ので、DB・SQLに自信がない方にもオススメです!

SQL 第2版 ゼロからはじめるデータベース操作

SQL 第2版 ゼロからはじめるデータベース操作

 

 次はDBについてのもう少し高度な本を読む予定です。

来週も頑張ります!

 

Railsでお買い物メモ & Amazon・楽天のランキング1位を返してくれるLINE bot作りました

みなさん、「あれ買わなきゃ!」って思った時どうしていますか?

(例:家のトイレで「あ、トイレットペーパーラスト1つやんけ、買わなきゃ」の時)

f:id:ysk_pro:20180826173319j:plain

僕はevernoteにメモったり、可能な時はその場でポチったり、今日の帰り道に買うぞって思って結局忘れちゃったりしています。

 

みなさんがどうしているか気になったので、Twitterアンケート取ってみました。

(協力いただいた方ありがとうございます)

 

みなさん同じような感じですね〜、記憶に頼ってる方が一番多い、という感じですね。

 

皆さんが常に使ってるアプリ、LINEでお買い物メモ取れたら便利じゃないですか?

 

さらにもう一つ。

買う商品ってどうやって選んでますか?

 

選ぶ時間が勿体無いので、僕はほとんどAmazonのランキング1位を何も考えずに買っちゃいます。

 

お買い物メモで、リストを表示するときにAmazon(or 楽天)の1位の商品とリンクを返してくれたら便利じゃないですか?

 

この2つを組み合わせてLINE bot作っちゃいました。

 

↓こちらの動画を見れば、使い方が分かると思います。

 

使い方はとてもシンプルです。

「買わなきゃいけないもの」を送信するとLINE botが覚えてくれます

「リスト」と送信するとそれまでに送信した買わなきゃいけないものリストとそれぞれのAmazon or 楽天のランキング1位の商品を返してくれます

Amazonor楽天と送信すると検索対象を切り替えられます

「クリア」と送信するとリストの中身を全て削除できます

 

買わなきゃいけないものをよく忘れちゃう方evernoteなどにメモしているけどちょっとめんどくさいな、と感じている方、是非一度使ってみてくださいー!

 

↓こちらのボタンから簡単にお友達追加できます!

友だち追加

 

また、作り方をまとめたチュートリアルを作成したのでご興味あればぜひご覧くださいー!

note.mu

【技術書メモ】オブジェクト指向設計実践ガイド 〜毎週アウトプットチャレンジ⑥〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第6弾ですー!

今回は、オブジェクト指向設計実践ガイド を読みました。

オブジェクト指向設計についてRubyで解説している名著です。

f:id:ysk_pro:20180826134302j:plain

はしがき

第1章 オブジェクト指向設計

  • オブジェクト指向設計では、世界をあらかじめ決められた手続きの集まりと考えるのではなく、オブジェクト間で受け渡されるメッセージの連続としてモデル化している
  • オブジェクト間の相互関係はオブジェクト間で受け渡されるメッセージであり、正しいメッセージを届けるには、メッセージの送り手が受け手のことを知っている必要がある。この依存関係がプログラムの変更を困難にしており、オブジェクト指向設計は依存関係を管理することでプログラムの変更を容易にしている
  • オブジェクト指向設計で最も良く知られているSOLIDという5つの原則
    • 単一責任(Single Responsibility)
    • オープン・クローズド(Open-Closed)
    • リスコフの置換(Liskov Substitution)
    • インターフェース分離(Interface Segregation)
    • 依存性逆転(Dependency Inversion)

第2章 単一責任のクラスを設計する

  • コードの変更が簡単であることの定義
    • 変更が副作用をもたらさない(見通しが良く、コード変更の影響が明白)
    • 要件の変更が小さければコードの変更も小さい
    • 既存のコードが簡単に再利用できる
  • クラスは単一の責任を持つべき:2つ以上の責任を持つクラスは簡単に再利用できない
  • クラスが単一責任かどうかを見極めるには、一文でクラスを説明してみる。「それと」や「また」が含まれていれば責任は2つ以上ある
  • メソッドも、クラスのように単一の責任を持つべきで、その理由や見極め方はクラスと同様である

第3章 依存関係を管理する

  • 一方のオブジェクトに変更を加えた時、他方のオブジェクトも変更せざるを得ないおそれがあるならば、片方に依存しているオブジェクトがある
  • オブジェクトが次のものを知っている時、オブジェクトには依存関係がある
    • 他のクラスの名前
    • メッセージが要求する引数
    • それら引数の順番
  • 依存関係の管理で鍵となるのは、依存の方向を制御すること。自分より変更されないものに依存することが問題解決の方法である

第4章 柔軟なインターフェースをつくる

  • インターフェースとは、クラス内のメソッドで、どのように何を外部に晒すかを説明するもの
  • パブリックインターフェースを作り上げるメソッドの特性
    • クラスの主要な責任を明らかにする
    • 外部から実行されることが想定される
    • 気まぐれに変更されない
    • 他者がそこに依存しても安全
    • テストで完全に文書化されている
  • プライベートインターフェースの特性
    • 実装の詳細に関わる
    • 他のオブジェクトから送られてくることは想定されていない
    • どんな理由でも変更され得る
    • 他者がそこに依存するのは危険
    • テストでは言及さえされないこともある
  • シーケンス図を使うことで、様々なオブジェクトの構成やメッセージ受け渡しの体系を簡潔に実験できる。シーケンス図は思考を明確にし、他の人と共同作業したり意思疎通したりするための手段となる

第5章 ダックタイピングでコストを削減する

  • ダックタイプはいかなる特定のクラスとも結びつかないパブリックインターフェースであり、クラスをまたぐインターフェースはアプリケーションに大きな柔軟性をもたらす
  • ダックタイプによって型付けされたオブジェクトは、そのクラスよりもその振る舞いによって定義される。ダックタイプという名前は、もしオブジェクトがダックのように鳴き、ダックのように歩くならば、そのクラスが何であれそれはダックであるという表現に由来する

第6章 継承によって振る舞いを獲得する

  • 承継とは、根本的にはメッセージの自動委譲の仕組みである。あるオブジェクトが受け取ったメッセージに応答できなければ、他のオブジェクトにそのメッセージを委譲するという関係
  • 未知のメッセージはスーパークラスの階層構造をさかのぼって委譲されていく。サブクラスとはスーパークラスのパブリックインターフェースを全て持っていると想定されるだけでなく、そのインターフェースに定義されるどのメッセージにも適切にレスポンスを返すことが求められる

第7章 モジュールでロールの振る舞いを共有する

  • オブジェクトが応答できるメッセージには次の4種類が含まれる
    • 自身が実装するメッセージ
    • 自身より上の階層のすべてのオブジェクトで実装されるメッセージ
    • 自身に追加されるすべてのモジュールで実装されるメッセージ
    • 自身より上の階層のオブジェクトに追加されるすべてのモジュールで実装されるメッセージ

第8章 コンポジションでオブジェクトを組み合わせる

  • コンポジションとは、組み合わされた全体が単なる部品の集合以上となるように、個別の部品を複雑な全体へと組み合わせること
  • コンポーズされたオブジェクトは、新たな組み合わせへと簡単に再編成できる、シンプルで分離したエンティティから構成される傾向にある

第9章 費用対効果の高いテストを設計する

  • 変更可能なコードを書くためには、価値の高いテストを書く能力が求められる。テストにより自信を持って絶えず継続的にリファクタリングができる
  • 良いテストは、コードへの変更によってテストの書き直しが強制されないように書かれている
  • テストは唯一信用できる設計の仕様書となる
  • テストはオブジェクトの境界に入ってくるか、出ていくメッセージに集中すべき。受信メッセージはその戻り値の値の状態がテストされるべきで、送信コマンドメッセージは送られたことがテストされるべきである 

おわりに

ここまで読んでいただきありがとうございます。

オブジェクト指向、難しいですね。

この本を繰り返し読んでオブジェクト指向設計を身につけていきましょう!

次からはSQLの本を読んでいく予定です。

来週も頑張ります!

【技術書メモ】なるほどUnixプロセス Rubyで学ぶUnixの基礎 〜毎週アウトプットチャレンジ⑤〜

毎週 1冊技術書を読んでブログでアウトプットするチャレンジの第5弾ですーー!
なんとか続いています、、、!習慣になってきた、、、!
 
Unixの基礎であるプロセスについてRubyで解説している本です。
 
読む前は、Unix?プロセス?? というお恥ずかしい状態だったのですが、本書を2周読み終えた今、少しずつ理解できてきました。
 
少しとっつきにくい内容かもしれませんが、知っていて損ではない内容だと思うので是非見てみてください。

f:id:ysk_pro:20180819120359j:plain

第3章 プロセスにはIDがある

  • システムで動作するすべてのプロセスは固有の識別子(プロセスID)があり、pidと呼ばれている
  • pidはプロセスにまつわる情報は何も持たずに、単に連番になっている数値のラベルである
  • pidはログファイルで有効に使われている。pidにより、ログファイルの各行がどのプロセスから出力されたものかを識別できる
 

第4章 プロセスには親がいる

  • 親プロセスはそのプロセスを起動したプロセスである
 

第5章 プロセスにはファイルディスクリプタがある

  • Unixの世界ではすべてがファイルであり、デバイスはファイルとして扱われる
  • 実行中のプロセスでリソースを開くと、ファイルディスクリプタ番号が割り当てられる
 

第6章 プロセスにはリソースの制限がある

  • カーネルによって1プロセスごとにリソースの制限が設定されている
  • 制限は設定を変更することでほぼ無限大にすることができる
 

第7章 プロセスには環境がある

  • 環境とは環境変数のことをいう
  • 環境変数はキーとバリューが対になっており、プロセスで使えるデータを保持している
  • すべてのプロセスは親プロセスから環境変数を引き継ぐ
 

第8章 プロセスには定数がある

  • RubyプロセスはARGVという特別な配列を参照できる
  • argvとは引数の配列を意味するargument vectorの略である
  • argvにはコマンドラインからプロセスに渡された引数が格納されている
  • プログラムにファイル名を渡したいケースにARGVが最もよく使われる
 

第9章 プロセスには名前がある

  • Unixプロセスにはプロセスの状態を知らせるための手段がほとんどなく、これを回避するためにログファイルを作成した
  • プロセスのレベルで情報を伝えるための仕組みは二つあり、一つはプロセス名でもう一つは終了コードである
 

第10章 プロセスには終了コードがある

  • 慣習としてプロセスは正常終了時には終了コード0を返す。それ以外の終了コードはエラーを示しており、終了コードごとに異なるエラーの種類を表す
  • raiseで送出された例外が捕捉されない場合もプロセスは終了する
 

第11章 プロセスは子プロセスを作れる

  • fork(2)で子プロセスを生成すると、実行中のプロセスの完全なコピーを生成でき、親プロセスで使われている全てのメモリのコピーを受け継ぐ
 

第12章 孤児プロセス

  • 親プロセスが死んでも子プロセスは生き続ける
  • デーモンプロセスとは意図的に孤児化されたプロセスであり、いつまでも動き続けることを狙いとしている
 

第13章 プロセスは優しい

  • fork(2)は親プロセスの完全なコピーを新しい子プロセスとして生成するが、物理的に全てのデータをコピーするのはかなりのオーバーヘッドになるため、コピー・オン・ライト(CoW)と呼ばれる仕組みを採用している
  • CoWは書き込みが必要となるまでメモリを実際にコピーしない。それまでの間、親プロセスと子プロセスとはメモリ上の同じデータを物理的に共有しており、親または子のいずれかで変更する必要が生じた時のみメモリをコピーすることで両者のプロセスの独立性を保っている
  • CoWはfork(2)で子プロセスを生成するときにリソースを節約できるのでとても便利な仕組みである
 

第14章 プロセスは待てる

  • 孤児プロセスが発生しないようにProcess.waitを使えば、子プロセスのいずれか1つが終了するまで親プロセスをブロックして待つことができる
  • 子プロセスを活用するのは、Unixプログラミングでよく使われるパターンである。こうしたパターンは子守りプロセスやマスター/ワーカー、preforkなどと呼ばれている
  • このパターンの肝は用意した1つのプロセスから並列処理のために複数の子プロセスを生成して、その後は子プロセスの面倒を見るというもの。子プロセスたちが応答するのかを確かめたり、子プロセスが終了した際には後始末をする
  • WebサーバのUnicornがこのパターンを採用している。Unicornではサーバ起動時にワーカープロセスをいくつ使うかを指定する。5つのインスタンスが必要だと指定した場合、unicornプロセスは起動後にWebリクエストをさばくための子プロセスを5つ生成する。親プロセスは子プロセスそれぞれの死活監視を行い、子プロセスがちゃんと応答できるようにする
 

第16章 プロセスはシグナルを受信できる

  • シグナルは非同期通信。プロセスはカーネル(OSの核となるプログラムで複数のプロセスを同時に実行するためのスケジュール管理やメモリの管理を行うもの)からシグナルを受けたとき、①シグナルを無視する、②特定の処理を行う、③デフォルトの処理を行う、のいずれかの処理を行う
  • シグナルはある特定のプロセスから別のプロセスへと送られるものであり、カーネルはその仲介役となっている
  • pidさえ分かれば、システム上のどのプロセスともシグナルで通信できる。シグナルはプロセス間の通信手段である
  • 現実世界でのシグナルは、サーバやデーモンといった長期間動き続けるプロセスで使われているのがほとんどである
 

第17章 プロセスは通信できる

  • プロセス間通信(IPC)で複数のプロセス間で情報をやりとりできる
  • パイプは単方向のデータの流れ。パイプを開くというのは、プロセスの片方の端を別のプロセスの片方の端につなぐことをいう。パイプを通じてデータを流すことができるようになるが、その方向は単方向に限られる。プロセスがパイプに対して書き込みではなく読み込み側となることを宣言した場合、そのパイプには書き込めない。逆も然り
  • パイプが単方向の通信手段であるのに対し、ソケットは双方向の通信手段である。親のソケットは子のソケットに読み書きできるし、逆も然り
 

第18章 デーモンプロセス

  • デーモンプロセスは、ユーザーに端末から制御されるのではなく、バックグラウンドで動作するプロセスである。デーモンプロセスのよくある例としては、Webサーバやデータベースサーバのように、リクエストをさばくためにバックグラウンドで常に動作するプロセスがある
  • デーモンプロセスはオペレーティングシステムの核でもある。さまざまなプロセスがバックグラウンドでずっと動作し続けているおかげで、システムは正常に動いている
  • プロセスを永遠に応答し続けられる状態にする必要がある場合にデーモンプロセスを用い、不要ならcronジョブなどのバックグラウンドジョブの仕組みを検討する
 

第19章 端末プロセスを作る

  • execve(2)は現在のプロセスを異なるるプロセスに置き換えられる。RubyプロセスをPhyhonや他のRubyプロセスに変えることができる
  • execve(2)によるプロセスの置き換えは元に戻すことができない
  • fork + execveの組み合わせは新しくプロセスを生成する際によく使われる。fork(2)で新しく子プロセスを生成して、それからその子プロセスを任意のプロセスに置き換えるためにexecve(2)を使う
 

第20章 おわりに

  • カーネルから見れば、どのプログラミング言語で書かれたプログラムも同じに見える。最終的には、すべてのコードはカーネルが理解可能な単純なものへコンパイルされる。そして、動作する段階ではすべてがプロセスとして同等に扱われる
  • Unixプログラミングはプログラミング言語を問わない。RubyスクリプトとCプログラムを連携させることもできる
  • シグナルを使えば、システム上のどんなプロセスも互いに情報を伝達できる。プロセスに名前を付けることで、コマンドライン上から誰でもプログラムの状況を検査できる。終了コードを使えば、呼び出し元のプロセスに成功/失敗のメッセージを伝えられる
 

付録A Resqueのプロセス管理

  • ResqueはRuby製の有名なジョブキューである
  • Resqueワーカーの仕事は、起動してアプリケーション環境を読み込んだらRedisに接続し、保留中のバックグラウンド・ジョブの実行を予約すること
  • Resqueワーカーはメモリ管理のためにfork(2)を使っている。Resqueはfork(2)を使うことで、ワーカープロセスのメモリ使用量が肥大化しないようにしている。Resqueがジョブを実行した後、メモリの使用状況は毎回ジョブの処理を行う前のきれいな状態に戻っている。メモリ解放の仕組みであるGCガベージコレクション)には課題があるため、fork(2)を使う方がメモリの使用量を抑えることができる
 

付録B Unicornのワーカープロセスの管理

  • Unicornは可能な限り仕事をカーネルに任せようとするWebサーバである
  • Unicornはパフォーマンスも信頼性も高く、GithubなどのRubyで作られた巨大なWebサイトでも数多くの採用事例がある
  • Unicornは大きく分ければpreforkサーバというカテゴリに属する。Unicornを起動する際にはワーカープロセスがいくつ必要なのかをUnicornに伝える必要がある。Unicornは起動するとまず、ネットワークソケットを初期化してアプリケーションをロードし、fork(2)を使ってワーカープロセスを生成する。
  • Unicornのマスタープロセスは、ワーカープロセスの死活監視をしたり、ワーカーがリクエストの処理に時間がかかりすぎていないかを検査する
 

付録C preforkサーバ

  • preforkは複数のプロセスを個別に生成するよりもメモリを効率的に使うことができる
  • 例えば、Unicornのワーカーを10個立ち上げるには11個のプロセスが必要になる。そのうち1つのプロセスがマスターとなり、他の10個のワーカープロセスの子守りをする。Unicornは起動時にマスタープロセスだけがRailsをロードするため、カーネルリソースの取り合いは発生しない
  • マスタープロセスはRailsをロードするのに3秒ほどかかるが、プロセスを10回フォークするのには、さほど時間はかからない。マスタープロセスはRailsを読み込むことで70MBのメモリを消費するが、コピー・オン・ライトのおかげで、子プロセスはマスタープロセスが使用しているのと同じデータについてはメモリを一切消費しなくて済む
 

おわりに

いかがでしたでしょうか。馴染みのない言葉ばかり出てくるので難しいですよね。

粘り強く読書を継続して、知識をつけていきましょう、、、!

 

引き続き、こちら(↓)の記事で紹介した本を順番にアウトプットしていく予定です。

ysk-pro.hatenablog.com

是非参考にしてみてくださいー!

来週もよろしくお願いします!