サンダーボルト

相手モンスターを全て破壊する。

文字コード技術入門 メモ

naotech.hatenablog.com

👆の記事に続き、文字コードに関する本を読んで勉強したことをメモします。読んだ本はこれ👇です。

f:id:nao_666:20200113120933j:plain
プログラマのための文字コード技術入門

以下、メモです。

絵文字

imodeとかの時代にJIS X 0208の未定義領域に携帯電話キャリア各社が独自に定義したのが最初。その後Unicodeに取り込まれた。文字と同じように、符号位置は定義しているがそのデザインまでは定義しておらず、送信者と受信者が同じデザインの絵文字を見ているとは限らない。

複数符号位置による装飾が可能で、【白黒の絵文字+絵文字スタイル符号(U+FE0F)】でカラフルな絵文字になったり、【人絵文字+肌の色】で肌色を調整できたり、また【女性👩+コンピュータ💻】で女性テクノロジストを表現できたりする。

UTF-16とBOMとUTF-8

UTF-16は16ビット単位である。そのとき上位8ビットと下位8ビットのどちらを先にデータで表現するかを決めないといけない。例えば「文」はU+6587だが、これを上位を先にすれば “65 87”、下位を先にすれば”87 65”。上位8ビットが先にくるものをビッグエンディアン(big-endian)と呼び、下位が先であればトルエンディアン(little-endian)と呼ぶ。ビッグエンディアンUTF-16をUTF-16BE、リトルエンディアンのものをUTF-16LEと呼ぶ。 これらのどちらを採用しているかを示すためにデータの先頭にバイト順マーク(BOM/Byte Order Mark)をつけることがある。BOMにはU+FEFFの符号位置を用い、ビッグエンディアンではデータの先頭に”FE FF”、リトルエンディアンでは”FF FE”というバイト列を付加することになる。

UTF-8にはBOMは必要無いが、ついている場合があり、それを想定していない実装だと予期せぬ結果になることも。

文字コード判別技術

ファイルを開いたとき、それがどんな文字コードで書かれているかを判別する技術について。

BOMによる判別

Unicodeの符号化方式の判別にはBOMを使える

  • FE FF xx xx : UTF-16BE
  • FF FE xx xx : UTF-16LE
  • 00 00 FE FF : UTF-32BE
  • FF FE 00 00 : UTF-32LE
  • EF BB BF : UTF-8

UTF-8はBOMが無い場合もある。

エスケープシーケンスによる判別

エスケープシーケンスを使うもの(ISO-2022-JP)と使わないもの(Shift_JIS)での判別が可能。さらにエスケープシーケンスの種類によってさらに細かく判別が可能。

バイト列の特徴を読む

たとえば、EUC-JPかShift_JISかを判別するとき、「0x80~0x9Fの値が出てくるようならまず間違いなくShift_JISというように使われやすい/にくいバイトといった特徴から読み取ることもできる。

おまけ:正しく判別させるテクニック(文書作成側の話)

うまくプログラムに判別してもらうために、「入」という文字を最初に書いたこともあった。 Shift_JISの「入」のバイトの一部はEUC-JPでは使われず、逆も然りであるため。ただ所詮は小手先のテクニック。

webについて

URLではASCIIを用いる。それ以外の文字はURL符号化(=URLエンコーディング/Percent Encoding)を行う。 URLをHTMLやXMLに書くときにクエリパラメータの区切りの&は&と書かなければいけない。

  • htmlやxmlの文書内部に<meta charset="utf-8"/>のように指定をする場合があるが、それを読むにはその文字列の文字コードを分かっておかなければならず、おかしなことになっている。ちょうど箱の中に鍵があるようなもの。現実にはその文字コード宣言はASCIIとして解釈できるようにする、としておくことで対処されている。つまり、ASCII互換の文字コードで解釈すればcharset宣言が理解できるはず、ということ。
    • とはいうものの、そもそもhttpのレスポンスのヘッダーのContent-Typeでcharsetを宣言すれば正しく伝えられる。

外字と環境依存文字

文字コードで余っている符号に当てはめられた文字を外字という。特にその中でもベンダー定義外字は機種依存文字(環境依存文字)と呼ばれるようになった。当然、文字化けが発生しやすい。

改行コード

2種類あり、CRとLFという名前がついている。利用されるときはそれぞれ1つか組み合わせの3通りがある。 CR : Carriage Return (タイプライターにて紙を右に動かし行頭から印字できるようにすること) LF : Line Feed (紙を上へ動かし次の行へ移動すること) それぞれASCIIではCR→0x0d、LF→0x0aという符号が与えられている。 CRとLFが混ざっていないか意識しながら機能を実装すべし。

CRとLFを動画で見たい場合はこれ😅

www.youtube.com

全角半角

文字コードは全角や半角を定めていない。文字を表示するプログラム側で1バイトのAと2バイトのAを区別して全角半角を表示しているだけ。 プログラムの利用者が混乱しないように機能開発すべし。

円記号問題

1バイトコードの0x5Cが文字コードによっては¥円マークであったり\バックスラッシュであったりする問題。例えばこのコードは韓国ではウォンを表すコードだったりもする。 HTMLをブラウザで表示する際、charsetをUTF-8にしていたとしてもlang属性によって円マークだったりバックスラッシュだったりが表示される。

試しに自分のPCで 「¥¥\」(全角円、半角円、バックスラッシュ) と売ってみる(UTF-8)と、バイトではそれぞれ 「EFBFA5」「C2A5」「5C」 となった。同じ文字をShift_JISとして保存すると 「818F」「5C」「5C」となり、たしかに円とバックスラッシュの見分けがつかなくなってしまった… つまり、Shift_JISで円と入力してUTF-8で閲覧した場合にバックスラッシュとなってしまう」ということになる。 確認のためShift_JISで「¥\」と入力して再度UTF-8Shift_JISで開き直すとどちらも「\\」となってしまった…破綻しとるやないか😅

文字コードを理解したい

これは何?

2020年の年始、こんなツイートをした

この中で実行可能なファイルをバイナリエディタで開いて「2019」を「2020」に書き換えた。このとき、2019は「32 30 31 39」と書かれていたのだが、UTF-8の文字コード表を見て、なるほど😁なったのも束の間、シフトJISの文字コード表を見ても同じ文字コードが書かれていてどっちやねん!?ってなった。これがこの記事の発端です。

UTF-8とかShift_JISとかUnicodeとかって何で、言葉の次元としてはどういう関係なのか?バイナリにはなぜ「32 30 31 39」と書かれていたのか?ソースコードのファイルのエンコードとは?このあたりをきっちり理解したいです。

言葉の定義を理解する

文字集合

(英:character set) 文字を要素とする集合のこと。例えば、アルファベットは「A~Z」を要素とする文字集合であるし、「あ〜ん」もひらがなの文字集合と言える

符号

一般には記号・しるしという意味。数学では特に+/-のこと(常に+/-を指す言葉だと思ってた!)

符号化文字集合

(英:coded character set) 印がつけられた文字集合のこと。つまり、文字集合の中の各々の文字を一意に特定できる記号(符号化表現)がつけられた文字集合のこと。 JIS X 0201JIS X 0208ISO/IEC 10646などがある。例えば、数字の「1」は31、「A」は41など(JIS X 0201の例)。このときの31や41といった符号をコードポイントと呼ぶ。

文字符号化方式

(英:character encoding scheme) ASCIIは単体で運用されることが多いが、他の符号化文字集合ではいくつかの符号化文字集合を組み合わせて利用したい場合がある。そこで、そういった複数の符号化文字集合を組み合わせて運用する方式を文字符号化方式と呼ぶ。

文字符号化方式にはShift_JISUTF-8などがある。Shift_JISJIS X 0201JIS X 0208を組み合わせたもの。また、UTF-8ISO/IEC 10646Unicodeで使える文字を収録している。

ポイントとしては、同じ文字を表していたとしても、符号化文字集合のコードポイントと文字符号化方式の符号(文字コード)は違う場合があるということ。例えば、Unicodeにおいて「あ」はU+3042と表し、UTF-8では16進数でE38182と表す。(つまり0xE38182。[0x]は後に続く文字が16進数であることを示す。)

文字符号化方式はコンピュータで利用する前提でコードが決められているが、符号化文字集合はそうとも限らないということもあり、こういった違いが発生する。

文字コード

文字をコンピュータで扱うためのバイト表現のこと。または、その文字とバイト表現の対応関係。 符号化文字集合はバイト表現であるとは限らないが、符号化文字集合文字符号化方式をまとめて文字コードと表現することもある。

エンコード

=符号化。あるデジタルデータを一定の規則に従って符号に変換すること。

例文:「あ」をUTF-8エンコードすると0xE38182になる。

文字コードを知る

ASCII

符号化文字集合の1つ。American Standard Code for Information Interchangeの略。

ラテン文字や数字などの英文でよく使われる文字を中心に、7ビットで表せる128種類の文字を収録している。

ASCII - Wikipedia

収録文字一覧を見てみると、基本的な文字、もう少し言えば基本的なプログラミング言語で必要な文字はだいたい網羅されてそう。

この時代から基本は1バイト単位でデータをやりとりしていたけど、なぜ7ビットかというと、1ビットはパリティビットに使っていたかららしい。パリティには奇数パリティと偶数パリティがあるが、例えば偶数パリティでは1バイトの中で1の個数が偶数になるように例えば一番左に1か0を追加する。もし文字コード部分が 0000001 だった場合、偶数パリティでは1の個数を偶数個(この場合は2個)にしたいので、先頭に1を足して 10000001とする

Unicode

符号化文字集合の1つ。

全世界の文字を1つの文字集合で扱うために開発された。これのPreface内Why Unicode?の箇所をみると、全ての文字が含まれた非常に膨大な、そしてプログラミングをする際に便利な文字コードを目指した旨が伝わってくる。

とにかくめちゃくちゃ量が多い。Unicodeの符号空間は16進数で 0 - 10FFFF である。つまり1,114,112符号位置が存在する。実際にはそのうち14万符号ほどに文字が割り当てられているみたい。

参考 :Unicode - Wikipedia

UTF-8

文字符号化方式の1つ。

基本的にはUnicodeに基づき1~4バイトで文字を表現する。ASCIIとの互換のため、ASCII文字は1バイトで表現している。

UTF-8では1~4の各バイトにルールがある。

  • 1バイト文字→先頭ビットは0
  • 2バイト文字の1バイト目→先頭は110
  • 3バイト文字の1バイト目→先頭は1110
  • 4バイト文字の1バイト目→先頭は11110
  • 2~4バイト文字の2バイト目以降の各バイト→先頭は10

このルールがあるおかげで、文字境界が確実に判別できる。例えば10001010だったら確実にある文字の2バイト目以降ということがわかる(先頭が10で始まってるから)。 ただあまりこの良さが分かってない😅どんなソフトウェアを作ればこの良さがわかるのかなぁ

参考:UTF-8 - Wikipedia

プログラミングにおける文字コードの扱い

ここからはプログラミングをする上でどのように文字コードが扱われているかの話。基本的にはGo言語を使って説明します。が、知らない人にもわかるように書くつもりです。

ソースコードのファイルの文字コード

ソースコード文字コードはどうなっているのかというと、GoにおいてはUTF-8で書くべきらしい。

Source code in Go is defined to be UTF-8 text; no other representation is allowed.

引用:Strings, bytes, runes and characters in Go - The Go Blog

ちなみにJavaだとJavaソースコードのファイル形式は指定できるみたい🤔

https://qiita.com/seraphy@github/items/98e2908b63af58ef0032

ここで試しにソースコードShift_JIS形式で作成し、go buildでビルドすると... なんとビルド成功、そして正しく実行できてしまった!

f:id:nao_666:20200105153116p:plain
できちゃった

で、UTF-8Shift_JISの1バイト文字のコードを見てみると、0x7Fまでは同じ値になっているみたい。Goではファイルの文字コードはとりあえずUTF-8であるという前提で動作するようにできているみたい。

しかし、よく見るとShift_JISの1バイト文字はUTF-8と違う文字(半角カタカナ等)も定義されている。あれ、これってもしかして...

Shift_JISの「マ」と「コ」の文字コードはそれぞれ cfba

f:id:nao_666:20200105152112p:plain
Shift_JIS文字コード

そしてUTF-8の「Ϻ」の文字コードCFBA

f:id:nao_666:20200105151339p:plain
UTF-8文字コード

つまり、ソースコードShift_JISにして 「マコ」を出力してみると...?? f:id:nao_666:20200105151606p:plain きたー!!

なるほどね😊つまり、ファイルの文字コードShift_JISの状態で「マコ」と入力して保存すると、ソースコードのファイルのバイナリではcfbaとして保存されている。そしてGoはコードをUTF-8として扱うようにできているので、それをUTF-8の文字として出力した。だから「Ϻ」って表示されたんですね。

最初の答え

自分がツイートした実行可能ファイルに2019が32 30 31 39と書かれていたのは、ソースコードUTF-8で書いていたから、その文字コードがそのまま書かれていたことが理由に見えますね。(buildしたタイミングで自分が把握していない何かの処理がある可能性は捨てきれませんが)

マスタリングTCP/IP 入門編 まとめ

これは何?

後で自分が復習できるように下記の本をまとめたものです。

f:id:nao_666:20200113194847j:plain
マスタリングTCP/IP 入門編

マスタリングTCP/IP 入門編

第1章ネットワーク基礎知識

1.1 コンピュータネットワーク登場の背景

1.2 コンピュータとネットワーク発展の7つの段階

  • 皆でマシン共有→仮想マシン共有→プライベートなネットワーク→インターネットという変遷

1.3 プロトコルとは

1.4 プロトコルは誰が決める?

1.5 プロトコルの階層化とOSI参照モデル

1.6 OSI参照モデルによる通信処理の例

1.7 通信方式の種類

  • 通信方式2種
  • 通信方法2種
    • 回線交換(例:電話)
    • 回線を占有
    • 通信速度は一定
    • パケット交換
    • パケットに分けて送信、回線共有
    • パケットはルーターの記憶領域(バッファ)に蓄積されてキューとして扱われ順に送信される
    • そのため蓄積交換とも呼ばれた
    • 通信速度が遅くなったり、ルーターのバッファを超えるパケットを受け取った場合、パケットが喪失されることがある
  • 通信相手の数による通信方式の分類4つ

1.8 アドレスとは

1.9 ネットワークの構成要素

  • 直接接続された機器間で通信するためのプロトコルやネットワークのことをデータリンクという
  • データリンクには、イーサネット、無線、ISDN等がある
  • イーサネットの通信媒体としては、同軸/ツイストペア/光ファイバーケーブル等があり、無線の通信媒体は電磁波である
  • 通信媒体によって伝送速度が異なる
  • 伝送速度の単位はbps(Bits Per Second)
  • 媒体中を流れる信号の速さは一定で、それでいて伝送速度が大きいというのは、速度が上がったのではなく、一度に送ることができるデータ量が増えたという意味
  • 実際のホスト間での転送速度はスループットと言われ、ホストのCPUのの能力や、混雑度、パケット中のデータが占める割合等も考慮した実効転送速度を意味する
  • リピーターは減衰して変形した信号の波形を増幅・整形する
  • 通信媒体を変換できるリピーターも存在するが、伝送速度の違う媒体間は接続できない(イーサネット10Mbpsと100Mbpsは接続できない)
  • リピーターは多段接続に関する制約がある(10Mbpsでは最大4つ、100Mbpsでは2つ等)
  • ブリッジはフレームを蓄積し、新たなフレームとして送る。多段接続に制限はない。伝送速度の異なるデータリンクを接続できる。
  • フレームとは、OSI参照モデル第二層(データリンク層)におけるパケットの呼び名
  • ラーニングブリッジは通信の送信元情報からどのホストがどのネットワークにあるかの情報を記憶し、無駄な通信を省いてくれる
  • ブリッジの機能を持ったハブを「スイッチングハブ」、リピーターの機能しかないハブを「リピーターハブ」と呼ぶ
  • ブリッジはMACアドレスで宛先を判別するがルーターIPアドレスで判別する
  • レイヤ4-7にはロードバランサーなどがある
  • 電話など即応性の高い通信を優先して扱うといった帯域制御もレイヤ4-7の仕事
  • ゲートウェイはデータを変換する(異なるプロトコルに変換する)
レイヤ
レイヤ4-7 アプリケーション層
プレゼンテーション層
セッション層
トランスポート層
ゲートウェイ
レイヤ3 ネットワーク層 ルーター
レイヤ2 データリンク層 ブリッジ
レイヤ1 物理層 リピーター

1.10 現在のネットワークの姿

  • ネットワークをつなぐ高速で主たるルーターをコア(バックボーン)と呼ぶ
  • また、コアのネットワークから抜ける各地点をエッジという
  • ネットワークには、混み合った経路を迂回して速く通信ができるようにされている工夫もある
  • LTEの規格では電話などの音声データもIPパケットとして転送することになっているが、実際には難しくまだできていない

第2章TCP/IP基礎知識

2.1 TCP/IP登場の背景とその歴史

  • ネットワークは軍事目的で開発が進み、ARPANETと呼ばれる実験で成功した後、TCP/IPが策定され、それがARPANETにも採用された。その後、UNIXにも実装され、流行していった。

2.2 TCP/IPの標準化

  • TCP/IPとは何を指す言葉かというと、TCPやIPを利用する上で必要となる多くのプロトコル群をまとめて指す言葉。例えばUDPTELNETFTP、HTTPなど
  • 標準化しようとする際には、RFC(Request for Comments)として仕様が公開される
  • 仕様策定の流れは Internet Draft → Proposed Draft(RFC) → Draft Standard → Standard
  • Standardになるには、実際に多く利用されていないといけない
  • RFC Editor http://www.rfc-editor.org/rfc/rfc-index.txt rfc/std以下にstandardが入ってるっぽい

2.3 インターネットの基礎知識

  • ネットワークとネットワークはNOC(Network Operation Center)で接続され、また、ネットワークの運用者や利用方針が違う場合、それらをつなぐものはIX(Internet Exchange)と呼ばれる
  • インターネットに接続するにはISP(Internet Service Provider)にお願いすることになる

2.4 TCP/IPプロトコルの階層モデル

2.5 TCP/IPの階層モデルと通信例

  • 各階層では上位層から受け取るものはすべて1つのデータとして認識され、それに自レイヤーでのヘッダを付加し、下位層に送る
用語 意味
パケット オールマイティな用語
フレーム データリンクのパケットを表す
データグラム IPやUDPなどネットワーク層以上でパケット単位のデータ構造をもつプロトコルで利用される
セグメント ストリームベースのTCPに含まれるデータを表す
メッセージ アプリケーションプロトコルのデータ単位を表す

第3章データリンク

3.1 データリンクの役割

  • データリンクという言葉はOSI参照モデルデータリンク層と具体的な通信手段(イーサネット無線LAN等)の2つを意味する言葉として用いられる
  • データリンクの「セグメント」とは、区切られた1つのネットワークを指す言葉だが、その区切りはどの階層の視点で見るかによって変わる。例えば、ネットワーク層から見ると1つのセグメントでも、物理層から見れば2つのセグメントということもありえる。
  • ネットワークの接続/構成形態のことをトポロジーと呼ぶ。バス/リング/スター/メッシュ型等がある

3.2 データリンクの技術

  • MACアドレスはデータリンクに接続しているノードを識別するために用いられる
  • バス/リング型のネットワークにおいては、すべてのステーションが送信されてきたフレームを受け取って、自分宛てじゃなければ破棄する
  • MACアドレスは、XX:XX:XX:XX:XX:XXという形式。Xは0~Fまでの16進数。合計6バイトのデータ
  • 通信媒体という観点からネットワークを分けると媒体共有型と媒体非共有型に分けられる
  • 媒体共有型にはコンテンション方式とトークンパッシング方式がある
    • コンテンション方式:データ送信権を競争にて取得し送信する方法。同時に復数が送信権を取得してしまった場合はデータが衝突し、壊れる(コリジョン(。ネットワークが混雑すると急激に性能が低下する。
    • トークンパッシング方式:トークンがネットワークを巡回し、これを持っているステーションだけがデータを送信できる。平等に送信権が配分され、混雑時にも性能が低下しにくいが、ネットワークが混雑していないと性能を発揮しにくい。
  • 媒体非共有型は今のイーサーネットでは基本になっていて、ハブとホストが1対1で結ばれていて、他のホストの回線を占有しない方式。また、この場合ツイストペアケーブルや光ファイバーケーブルを使えば、ケーブル内の2本の線を使い同時に送受信を行える(全二重通信)。これに対してトランシーバーのようなものは半二重通信と呼ばれる。
  • イーサネットスイッチは、復数のポートを持ったブリッジで、転送表(フォワーディングテーブル)でMACアドレスを管理し、学習しながら効率的に通信を行う
  • ブリッジの接続を間違うとループが起きる。これを解決するのがスパニングツリーとソースルーティングという方式
    • スパニングツリー:BPUDというパケットを交換し、ループが起きていないかを検知し、問題があれば一部ポートを閉じる。障害時にはそのポートを開放することもある
    • ソースルーティング:送信側が送信経路を指定する方式
    • VLAN(Virtual Lan)機能を使い、VLAN IDを発行すれば同じスイッチにつながったネットワークでもセグメントを分けることができる

3.3 イーサネット

  • イーサネットには様々な規格があり、通信速度の違うものどうしを接続する場合はルーター等が必要になる
  • 当初イーサネットは半二重通信が前提だったが、改良が行われ全二重通信となった
  • オクテット:8ビットが1オクテット。8ビットであることを特に強調したい場合に、バイトよりオクテットを使う
  • イーサネットフレームの先頭にはプリアンブルと呼ばれる8オクテットのフィールド(101010…11)がつけられる。これは今からイーサネットフレームが始まるということを伝える
  • プリアンブルの後にはフレーム本体が付き、本体は宛先MAC(6)+送信元MAC(6)+タイプ(2)+データ(46~1500)+FCS(4) となっている
    • FCSはFrame Check Sequenceといって、データが壊れていないかをチェックする

3.4 無線通信

  • LAN(Local Area Network)の範囲を比較的高速で接続する無線を無線LANと呼ぶ
分類 通信距離 団体や技術
無線PAN (Personal) 10m Bluetooth
無線LAN (Local) 100m Wi-Fi
無線MAN (Metropolitan) 数km〜100km WiMAX
無線RAN (Regional) 200km〜700km
無線WAN (Wide) 3G、LTE、4G
  • Wi-Fi(Wireless Fidelity[忠実、忠誠])はWECA(Wireless Ethernet Compatibility Alliance)[現Wi-Fi Alliance]によってIEEE802.11規格群の普及を目的として付けられたブランド名
  • WiMAX(Worldwide Interoperability for Microwave Access)は、大都市圏をエリアとした広範囲なワイヤレスネットワーク

3.5 PPP (Point-to-Point Protocol)

3.6 その他のデータリンク

  • HDMIはHigh-Definition Multimedia Interfaceで、高品質な映像と音声をデジタル伝送できる規格。バージョン1.4からイーサネットのフレームを伝送する規格が追加され、HDMIケーブルでTCP/IPによる通信が可能になる

3.7 公衆アクセス網

  • IP-VPNでは、IPネットワーク上にMPLS(Multiprotocol Label Switching)技術を用いてVPNを構築できる。MPLSはラベル(タグ)をIPパケットに付加して通信を制御する。このラベルを顧客ごとに異なるように設定し、MPLS網を通過するときに宛先の判断を行う

第4章IPプロトコル

4.1 IPはネットワーク層プロトコル

  • IPアドレスが付けられた機器をホスト、付けられかつ、経路制御を行う機器をルーター、それら2つをまとめてノードと呼ぶ
  • データリンク層では同じデータリンク内で接続されているノード間の通信を行うが、ネットワーク層では異なるデータリンク間での通信を行う
  • ネットワーク層の役割を一言で表すと終点ノード間の通信(end-to-end)を実現すること

4.2 IPの基礎知識

4.3 IPアドレスの基礎知識

  • IPアドレス(IPv4アドレス)は32(ドット区切り8ビット*4)ビットで表される
10101100. 00010100. 00000000. 00000001
172. 20. 0. 1
  • 組み合わせは232=4,294,967,296あり、約43億台のコンピュータをIPネットワークにつなげるように思えるが、IPアドレスはネットワーク部とホスト部に分けられるため実際にIPネットワークに接続できるコンピュータ数はそれより少ない
  • IPアドレスのネットワーク部はセグメントが異なれば違う値
  • IPアドレスホスト部はセグメントが同じであれば違う値
  • 192.168.144.10/24のネットワーク部は先頭から24ビットなので192.168.144の部分
  • 上の例ではサブネットマスクによりネットワーク部とホスト部を示していたが、クラスによる分け方もある
  • ホスト部がすべて0のIPアドレスはネットワークアドレスを表したりIPアドレスが不明な場合に使うことがあるので基本は使わない、またホスト部が全て1のアドレスはブロードキャストアドレスとして使う
  • ローカルブロードキャスト
    • 192.168.0.0/24ネットワーク内で192.168.0.255に送信するとそのネットワーク内全てに送られる
  • ダイレクトブロードキャスト
    • 192.168.0.0/24内のホストから192.168.1.255という192.168.1.0/24ネットワークへダイレクトブロードキャストすると、192.168.0.0/24内ではもちろんブロードキャストされず、192.168.1.0/24内の全てのホストに届く
  • クラスは無駄が多い。例えばBクラスの場合上位16ビットがネットワークアドレス部、下位16ビットがホスト部となり、つまり1ネットワーク内に216=65536個のホストが接続できることになるが、現実的にそんな大量のホストをつなぐことはないから。
  • クラスAやBをそのまま使うのは非常に無駄で、ネットワークアドレスが不足してしまうためAやBをそのまま使うことは許されなくなり、そのための仕組みがサブネットマスク
  • サブネットマスクを使えば柔軟にネットワークアドレス部を指定できる
  • 例えば 172.20.100.52 /26 は前から26bitがネットワークアドレス部であることを示す。52は00110100なので、最初の00までがネットワークアドレス。
  • IPアドレスが枯渇するということで、グローバルとプライベートを分けた
    • クラスA:10.0.0.0〜10.255.255.255 (/8)
    • クラスB:172.16.0.0〜172.31.255.255 (/12)
    • クラスC:192.168.0.0〜192.168.255.255 (/16)
    • ↑考えればわかるが、全てネットワークアドレス部は固定となっている
    • クラスBは 172.00010000.0.0〜172.00011111.255.255で、上位12bitは値が同じ
  • 一般的にはグローバルに公開するルーター等のみだけグローバルIPを使い、公開していないものはプライベートIPを使う
  • IPv4が枯渇してきているがIPv6が普及していないためなんとかIPv4でうまく運用している
  • グローバルIPICANN(Internet Corporation for Assigned Names and Numbers)で一元管理されており、日本ではJPNIC(Japan Network Information Center)が管理している

4.4 経路制御(ルーティング)

  • 経路制御表にはネットワークアドレスと次のルーターのアドレスが書かれており、もし複数のネットワークアドレスに一致した場合は一致するビット列が長いほうのネットワークアドレスを選択する(最長一致)

4.5 IPの分割処理と再構築処理

  • データリンクによって最大転送単位(MTU)が違うためIPはデータを分割する
  • 再構築処理は途中のルーターでは行わず、最後だけでやる。なぜなら全てのパケットが同じ経路で来る保証がないし、コストがかかるから
  • 経路MTU探索:ある経路でのMTUを予め試行して求めておきそれで最初から分割しておくることで無駄な分割コストをカットできる

4.6 IPv6 (IP version 6)

  • IPv6は128ビットで枯渇問題の解決とIPv4との互換性を持たせる努力がされている
  • IPv6の特徴
    • 経路MTU探索を利用しルーターに分割処理をさせない
    • ヘッダ長を固定(40オクテット)等
  • 16進数用いて表し、また0:0:と続くところでは(::)で省略できる(省略は1箇所のみ)
    • 例)FEDC:4534:ACDD:2594:BA98:FEDC:7654:3210
    • 1080:0:0:0:8:800:200C:417A→省略→1080::8:800:200C:417A
  • グローバルユニキャストアドレス:世界で一意のアドレス
  • リンクローカルユニキャストアドレス:データリンク内でユニーク
  • ユニークローカルアドレス:インターネット通信を行わない場合のアドレス
  • IPv6では最小のMTUは1280オクテットと決められているため、CPUやメモリに制限がある場合は、機器の実装時に分割時探索をせずに1280オクテット固定で分割、送信してもよい

4.7 IPv4ヘッダ

4.8 IPv6のヘッダフォーマット

第5章IPに関連する技術

5.1 IPだけでは通信できない

5.2 DNS (Domain Name System)

  • DNSは名前からIPへ変換する
  • DNSによる問い合わせ手順(kusa.ac.jp内のリゾルバがwww.ietf.orgと通信したい場合)
    • kusa.ac.jpのDNSサーバーに問い合わせ
    • DNSがルートネームサーバーにwww.ietf.orgのIPを問い合わせ
    • ルートネームサーバーがietf.orgのIPを返却
    • DNSietf.orgのDNSにwww.ietf.orgのIPを問い合わせ
    • DNSがリゾルバにIPを返却
    • ゾルバからwww.ietf.orgへIPを使って通信
  • DNSはホスト名→IPの紐付けだけではなく他にもデータを管理している
    • Aレコード:ホスト名→IP
    • PTR:IP→ホスト名
    • NS:上位や下位のネームサーバーのIPアドレス
    • MX:メールアドレスとメールサーバーの紐付け

5.3 ARP (Address Resolution Protocol)

5.4 ICMP (Internet Control Message Protocol)

  • IPでの通信がうまくいかなかったとき等に助けてくれるのがICMP。エラーを通知したりネットワークの診断を行ったりする
  • IPのTTLが0になったときはICMPのTime Exceeded Messageを返却する
    • これを利用しているのがtracerouteで、TTLを1からインクリメントしてICMPのTime Exceeded Messageを順に受け取り実現している
  • ICMPのエコー要求とエコー応答メッセージを利用しているのがpingコマンド
  • ICMPv6はIPv6のためのもので、IPv4ではICMPがなくても通信できるがIPv6ではICMPv6が必須。IPv6ではIPからMACを調べるプロトコルARPからICMPの近隣探索メッセージに変更される

5.5 DHCP (Dynamic Host Configuration Protocol)

  • DHCPサービスが行われているネットワークでは、クライアントをつなげばすぐにネットワークに接続できる(Plug and Play)。IPアドレスDNSサーバー等の情報を自動で設定してくれる
  • クライアントがDHCPサーバーからIPアドレスを取得するときはDHCPへ発見パケット→提供パケット→要求パケット→確認応答パケットと2往復する
    • 2往復するのは複数のDHCPサーバーがあっても正しく動作させるため

5.6 NAT (Network Address Translator)

  • NATはプライベートIPでグローバルに接続するためのもので、NAT対応ルーターがリクエストを送信する際にプライベートIPをグローバルIPに書き換える。複数のプライベートIPが同じグローバルIPを共有することになる
  • NAPT(NAPortsT)を使えばポートを含めてIPの変換テーブルを作るためプライベートIPを使ってグローバルに送受信できるようになる
  • NAT-PT(Protocol Translation)は、IPv6ヘッダとIPv4ヘッダを付け替える技術で、これによりIPv6しか設定されていないホストでも、IPv4の環境と通信できる

5.7 IPトンネリング

  • [IPv6]-[IPv4]-[IPv6] という構成のとき、IPv6の2つがIPv6どうしで通信するのは不可能なはずだが、IPv4を通過する際にIPヘッダの次にIPヘッダをつなげ、上位層のヘッダを付けないようにすればIPv6どうしで通信できる。この技術をIPトンネリングという

5.8 その他のIP関連技術

  • マルチキャストをしたいホストはルーターにIGMP(Internet Group Management Protocol)で受信したい旨を伝える(マルチキャストアドレスを通知)
  • 移動してもIPを変えない技術がMobile IP
    • 移動したら、もとの場所のホームエージェントが移動したホストのふりをしてARPパケットを送り、パケットを受信し、さらにトンネリングして移動後のホストに転送する
    • ホームエージェントとは、移動ホストがどこにいるか監視し、移動先にパケットを転送するもの。戸籍を登録した役所のようなもの

第6章TCPUDP

6.1 トランスポート層の役割

  • トランスポート層では宛先のプログラムを指定する
  • TCP/IPでのトランスポート層は2つ、TCP(Transmission Control Protocol)とUDP(User Datagram Protocol)
  • TCPはコネクション指向、ストリーム型で順序制御や再送制御を行い信頼性を提供する
  • UDPは信頼性がなく、送信したメッセージの大きさは保たれるが到達する保証がないためアプリケーション側で到達の確認や再送処理が必要
  • TCPはメールなど、UDPIP電話などに適する。もしIP電話TCPで実装した場合、音声が遅れてしまう

6.2 ポート番号

6.3 UDP

  • UDPコネクションレス、信頼性がない、高速なため、総パケット数が少ないDNSSNMP、動画や音声、同報性が必要なブロードキャストなどに向いている

6.4 TCP

  • TCPはコネクションの確立、終了、維持といったことを行う
  • TCPではデータが受信ホストに到達したときに、到達したことを知らせる確認応答(ACK : Positive Acknowledgement)を送信元に送ることで信頼性を提供している。うまく受信できなかったときは否定確認応答(NACK : Negative Acknowledgement)を送る
  • TCPでパケットを送信後、再送するまでに、どれくらいの時間ACKを待てばよいかというのは、これまでの通信の実績から計算する。Round Trip Time(往復時間)と分散を計測して計算する
  • UNIXWIndowsは再送のタイムアウトを0.5秒単位で設定しているが、最初の通信では推測できないので、デフォルトで6秒程度に設定されている
  • TCPではコネクション確立時に通信を行うデータ単位(MSS : Maximum Segment Size)を決める
    • 理想的なサイズはIPで分割されない最大の単位。
    • 送信ホストと受信ホストがお互いに候補を提示し小さい方の数値に決まる
  • 確認応答による低速度を防ぐためにいくつかのセグメントをまとめて「ウィンドウ」という単位を作り、それごとに確認応答を行う
  • TCPではネットワークの利用効率を高めるために、
    • すべての送信済みデータが確認応答されている
    • 最大セグメント長(MSS)のデータを送信できる
    • の両方に当てはまらないときはデータ送信をしばらく待つ(Nagleアルゴリズム)
  • TCPでは確認応答と実際のデータ返送のパケットを1つにして送ることができ、これをピギーバックという

6.5 その他のトランスポートプロトコル

6.6 UDPヘッダのフォーマット

6.7 TCPヘッダのフォーマット

  • TCPのヘッダにのチェックサムは、途中のルーターのメモリ故障やプログラムのバグによってデータが破壊されていないことを保証するため。ノイズによる通信途中のビットのエラーはデータリンクのFCSで検出できるはず。

第7章ルーティングプロトコル(経路制御プロトコル)

7.1 経路制御(ルーティング)とは

  • ルーターが正しい方向に通信を導くことをルーティングという
  • スタティックルーティングでは手で経路情報を入力するが、ダイナミックルーティングでは隣り合うルーター間で接続情報を教え合い、これが連なって経路制御表が完成する

7.2 経路を制御する範囲

  • 経路制御に関するルールを決めて、それをもとに運用する範囲を自律システム(AS : Autonomous System)といい、例えばISPがそれである
  • 自律システム内部でダイナミックルーティングに利用されるのがIGP(Interior Gateway PRotocol)で、自律システム間の経路制御に利用されるのがEGP(Exterior Gateway PRotocol)

7.3 経路制御アルゴリズム

  • 距離ベクトル型(Distance-Vector)アルゴリズムでは、あるルーターからその次のルーターを選択する際、目的地となるホストへの距離だけを知っており、それが最短となるルーターへと制御する。
  • リンク状態型(Link-State)では接続地図全体をルーターが知っており、それをもとに最短経路を判断し制御する。距離だけでなく、どういう経路かまで把握した上で制御している

7.4 RIP(Routing Information Protocol)

  • ルーターはRIPで経路制御情報を30秒周期でブロードキャストする。受け取る側はこの情報が6回連続で来なくなったら接続が切れたと判断する。
    • ルーターAから情報をもらったBは自分の距離分の1を足してまた情報をブロードキャストする
  • 距離の単位はホップ数(=通過するルーター数)
  • RIP2はRIPを改良したもので、経路制御情報の交換にブロードキャストではなくマルチキャストを用いたり、サブネットマスク対応が行われたりしたもの

7.5 OSPF(Open Shortest Path First)

  • OSPFはリンク状態型のルーティングプロトコル
  • サブネットマスクに対応しており、可変長サブネットで構成されたネットワークの経路制御が可能になった

7.6 BGP(Border Gateway Protocol)

  • BGPは組織間を接続するときに利用されるプロトコルで、EGPの一種。
  • BGPでも最終的な経路制御表はネットワークアドレスと次に配送すべきルーターの組で表されるが、BGPでは通過するASの数をもとに経路制御を行う
  • JPNICが管理しているAS番号の一覧はここから https://www.nic.ad.jp/ja/ip/as-numbers.txt
  • 例えば、AS1とAS3がつながっていない場合、例えばそのどちらもとつながっているAS2が中継してくれないとダメで、もししてくれない場合専用回線を準備しないといけない
  • BGPにより経路制御情報を交換するルーターをBGPスピーカーという
  • BGPでは目的とするネットワークアドレスにパケットを送った際に通過したASの数を距離としてその数が少ない経路を基本的に使う
  • BGPでは経路情報として、経路(途中のルーター)を把握しており、距離だけを知っているわけではない。また、リンク状態でもない。これを経路ベクトル型(Path Vector)と呼ぶ。

7.7 MPLS(Multi Protocol Label Switching)

  • IPパケット転送にはIPアドレスの最長一致によるルーティングだけではなく、それぞれのIPパケットにラベルという値を設定し、それに基づいて転送する方法もあり、その代表がMPLSである

第8章アプリケーションプロトコル

8.1 アプリケーションプロトコルの概要

  • TCP/IPのアプリケーション層にはOSI参照モデルの5,6,7層であるセッション、プレゼンテーション、アプリケーション層の全ての役割が含まれている

8.2 遠隔ログイン(TELNETSSH

  • SSH = Secure SHell
  • TELNETではログイン時のパスワードが暗号化されずに送信されるため盗聴されると不正侵入される危険性があったが、SSHであれば通信内容が暗号化されるため盗聴されたとしてもパスワードや入力したコマンド、その結果が分からなくなる
  • SSHにはポートフォワード機能がある。例えばローカルの8080にアクセスしたら、それをsshサーバーに転送してそのサーバーから見たホストXの80番ポートに転送、といったことができる ssh -L 8080:X:80 remote
    • これを利用しているのがVPNである

8.3 ファイル転送(FTP

  • FTPでは2つのTCPコネクションが利用される。1つは制御用、もう1つはデータ転送用

8.4 電子メール(E-Mail)

  • メールはSMTP(Simple Mail Transfer Protocol)によって提供される
  • 初期の電子メールでは電子メールの送信者が利用しているコンピュータと宛先のコンピュータ間で直接TCPコネクションが張られて電子メールが配送されていた
    • その方法だと同時に電源が入っていないと届かず、運用が厳しいので常に電源が入っているメールサーバーを経由するようになった。そのためのプロトコルがPOP(Post Office Protocol)である
  • 電子メールの配送先の管理はDNSによって行われており、メールアドレスとそのメールアドレス宛のメールを送信すべきメールサーバーのドメイン名を登録する。これがMXレコード
  • MIME(Multipurpose Internet Mail Extensions)によってメールで転送できるデータ形式を拡張して、メールで静止画や動画、音声、その他のファイルなど様々なものを送ることができる
  • SMTPはメールを送信するためのプロトコル、POPはメールサーバーからメールを受け取るためのプロトコル
  • IMAPはPOPのようにメールを受信するためのプロトコルであるが、メールのデータをクライアントではなくサーバーで管理することが特徴。これによって複数のコンピュータでメールを確認することができる

8.5 WWW(World Wide Web

  • URIはIdentifier、URLはLocatorで、URIはインターネットに限らずあらゆる資源を識別できるよう考えられた識別子
  • URIのスキーム一覧 https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
  • HTTP1.0までは1つの「コマンド」と「応答」をやり取りするたびにTCPコネクションを確立し、切断していたが、HTTP1.1からは1つのコネクションで複数のコマンド/応答を行えるようになり、TCPのコネクションの確立/切断によるオーバーヘッドが減った

8.6 メットワーク管理(SNMP

  • SNMP(Simple Network Management Protocol)はネットワーク管理のためのプロトコル

8.7 その他のアプリケーションプロトコル

  • インターネット電話やビデオ会議の呼び出しを行うためのプロトコルH.323SIPなどがある
  • UDPは信頼性がないため、パケットが喪失したり順番が入れ替わったりすることがある。UDPでリアルタイムなマルチメディア通信を実現するためには、パケットの順序や送信時刻を管理する必要があり、これを行うのがRTP(Real-Time Protocol)
  • RTPはそれぞれのパケットにタイムスタンプとシーケンス番号を付加し、これによって受け取り側はマルチメディアの再生タイミング調整でき、パケットの抜けを把握できる
  • MP3=MPEG1 Audio Layer Ⅲ
  • 例えば電子メールはメールサーバーに複数のクライアントが接続する1:Nの通信形態だが、端末どうしで接続する1:1の通信形態をP2P(Peer To Peer)と呼ぶ
    • Skypeはこれを使っている
  • サーバークライアントモデルでは、クライアントはNATの内側でも問題ないが、P2PではNATを超えて双方の端末に接続できる必要がある

第9章セキュリティ

9.1 TCP/IPとセキュリティ

9.2 セキュリティの構成要素

  • ファイアウォールにはたくさんの種類/形態があり、規定されたパケットのみを通過させる/させないパケットフィルタリングタイプや、アプリケーションを介在させ不正な接続を遮断するアプリケーションゲートウェイタイプなどがある
  • ファイアウォールの共通的な考え方は、「危険にさらすのは特定のホストやルーターのみに限定する」ということ
  • ファイアウォールでは、例えばTCPのコネクション確立要求パケットはあるネットワークの外部からのものは破棄し内部からインターネットに向けてのものは許可する、といったことができる
    • TCPヘッダのSYNが1でACKが0のTCPパケットがインターネット側から流れてきたときには遮断する、とすれば実現可
  • ファイアウォールを通過した悪意のある通信を検知するためのものがIDS(侵入検知システム)
  • PKI(Public Key Infrastructure : 公開鍵基盤)は、通信の相手が本物かを第三者に証明してもらうための仕組み。この第三者をCA(Certification Authority : 認証局)と呼ぶ
    • 利用者はCAが発行する証明書に記載された通信相手の秘密鍵に対応する公開鍵を使い暗号化し通信する
    • これは暗号化メールやHTTPSによるWebサーバーとの通信で利用されている

9.3 暗号化技術の基礎

階層 暗号化技術
アプリケーション SSH, SSL-Telnet
セッション、トランスポート SSL/TLS, SOCKS V5の暗号化
ネットワーク IPsec
データリンク Ethernet, WANの暗号化装置

9.4 セキュリティのためのプロトコル

  • VPNを構築するときに使われるのがIPsecで、IPヘッダの後に暗号ヘッダや認証ヘッダをつけ、そのヘッダ以降のデータを暗号化して解読できないようにする
  • WebではTLS/SSLを使ってHTTP通信の暗号化を行う。それがHTTPSである
    • Transport Layer SecurityとSecure Sockets Layerの略。最初にNetscape社が提案したときはSSLだったが標準化に際してTLSとなったがSSLとまとめて呼ぶ場合もある
  • HTTPS通信を行うまでの、クライアントとサーバーのやりとりは以下
1. クライアントがサーバーにHTTPSでアクセス
2. サーバーが「公開鍵A」と「証明書」をクライアントへ送信
3. クライアントが「証明書」のCAを確認し、CAの公開鍵を取得、それを利用して証明書を復号化
4. クライアントが復号化した証明書を見て通信相手が本物かを判断し、
   本物であるとわかった場合は「共通鍵」を作成
5. クライアントが、サーバーからもらった公開鍵Aを用いて4で作成した共通鍵を暗号化し、サーバーへ送信
6. サーバーが受け取ったデータを秘密鍵で復号化し共通鍵を知る
7. お互いにクライアントが作成した共通鍵を知ることができたため、ここからHTTPS通信が可能となる!
  • 公衆無線LANなどでID/パスワードで認証をかけて限られた人にのみネットワークを利用させるために用いられる認証の仕組みがIEEE802.1X
    • IEEE802.1Xでは認証されていない端末には一時的なIPを付与し、認証サーバーとのみ通信できるようにしておき、認証されたらIPアドレスを再度付与してインターネット接続を提供する

Webを支える技術 メモ

この記事は何?

以下を読んだのでメモ

f:id:nao_666:20200113195042j:plain
Webを支える技術

メモ

Webの構成要素

まず、もちろんだけどインターネット=Webではない。最初はインターネットができて世界がつながるようになったけど、メールとかしかなくて、しかもメールでも初期は送信側と受信側が同時に電源がついてないと届かないみたいな時代があった。 そこにWebが登場した。WebはHTML, HTTP, URIで構成される。HTMLがフォーマット、HTTPがプロトコルURIがドキュメントを一意に特定するもの。これらが出現したことで一気にWebがインターネットにおいて主流になり、栄えることとなった。

また、HTTPはステートレスなプロトコルとして設計されている。そのため、サーバー側の作りがシンプル(関数的)になる。ステートフルだとスケールしにくい(サーバー台数が増えたときの同期のオーバーヘッド)という問題もある。しかし、ステートレスな設計にも問題はあり、

  1. 認証などの決まった処理を繰り返すコストがかかる
  2. 送信データが増える

といったものが挙げられる。 認証にSessionを使うのはHTTPの考え方からすると反しているように思えるし、そういう意味ではJWTはHTTP的なのかなとも思う。

URI設計

URI設計はER図、クラス図、情報アーキテクチャ(すでに存在するWebサイト等)を参考にすることができる。また、COOLなURIは変わらない。言語に依存したURI等は避けるべき。

ER図

ER図を参考にする場合、例えばDBの1レコードを1リソースとして扱うことが考えられる

クラス図

1:n(has a)の関係が見えたらそれをURIの階層構造として表示したり、継承(is-a)の関係ならURIでは同階層で表現できないかを検討できる。

情報アーキテクチャ

もうすでにあるテーマをWebサイトとして表現しているようなものが存在する場合、そのサイトマップ、構成をURIの参考にできる。例えば、Webサイトのリンク関係を図にして関係性を見る。

その他

改めて、リクエスト/レスポンスヘッダをいろいろ見ると面白い。 例えば、

Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7

は、Shift_JISが優先度1、その他は0.7で受け付けるというネゴシエーション

【要約と感想】THE TEAM 5つの法則

概要 良いチームを作るための法則を大きく5つに分けて解説している。科学的な根拠となる論文等も一緒に紹介されている。

f:id:nao_666:20200113193653j:plain
THE TEAM 5つの法則

要約

第一章 Aim(目標設定)の法則

  • 共通の目的(目標)を持った集団がチームである。目的が無ければそれはただのグループ。
  • 目標には3種類ある(例はTHE TEAMの執筆チームの目標)
    1. 意義目標(日本全体のチーム力を高める)
    2. 成果目標(10万部売る)
    3. 行動目標(チームの法則を事例を交えてわかりやすく伝える本をつくる)
  • 意義目標の方がブレイクスルーが起きやすく、行動目標の方がアクションが分かりやすい
  • チームメンバーが自分で考え動くことができるのであれば1を、そうでなければ3を設定すると良い。もちろん、複数組み合わせて設定してもよい。
  • ただし意義目標が無いと、単純に作業をやるだけになってしまいがち。意義目標も設定することが推奨される。
  • 自分がチームに目標を設定する際はそれぞれの目標がうまくつながっているか、それを日々意識できているかをチェックすべし

第二章 Boarding(人員選定)の法則

  • メンバー選びは非常に大事。それと同様に、誰を外すかも非常に大事。
  • Boardingを語る上では、チームを4パターンに分けて考える
    f:id:nao_666:20190703003335j:plain
    チームの4タイプ (THE TEAMより引用)
  • メンバーが入れ替わらないチームがいいチームだ、とは一概に言えない
  • 環境の変化が多いチーム(柔道型、サッカー型)では、チームの入口出口どちらものハードルを下げ、その都度適応するチームを作るのが大事
  • 逆に環境が変わらなければ厳選採用するのが大事
  • 自分のチームの流動性に応じてどのように入口出口のハードルを設定するかを考えよう
  • 多様性のあるチームが良い、とも一概には言えない
  • 例えば人材の連携度合いの低い(柔道型、駅伝型)、個人で完結するタスクの場合は、それが得意な同じような人材を集めた方がよい。
  • ただし、最近では多様性のあるチームの重要性が叫ばれることが多いのも事実である。これはビジネスが第二次産業から第三次産業へ移ってきているため、環境の変化の度合いが大きい仕事(対人の仕事)が増えてきていることが理由だと考えられる。

第三章 Communication(意思疎通)の法則

  • チームの行動をコミュニケーションだけで決めようとするとかなりの手間がかかる
  • 適切なルールを設定することで、必要なコミュニケーションだけをとることができ、チームの効率があがる
  • ルールが少なすぎても、多すぎてもコミュニケーションが増えてしまうのでうまくバランスをとるべき
  • 以降、ルール設定のポイントを4W1Hに沿ってまとめる

ルールの設定粒度(What)

  • 人材の連携度合いが少ない(柔道型、駅伝型)チームはルールは比較的少なくして済むはず。なぜなら、ルールは人と人が連携するときに必要になるものだから。
  • 環境の変化度合いが大きい(柔道型、サッカー型)チームはルールを細かく設定する必要がないはず。なぜなら、環境が変わってしまえばルールが活用できなくなる可能性が高い。

設定粒度について意識をしながら、まずは基本となる最初の4つのルールを決めていく。

権限規定のルール(Who)

  • 「誰がどこまで決めていいのか」ということをまず決めなければならない
  • メンバーがどこまで自分で判断してよいのか、どこからチームとしての判断を仰ぐべきなのかを明確にしておかなければ、チームの活動効率が下がってしまうため、それを決めておくべきである
  • 人材の連携度合いが小さい活動は、メンバーが自分の活動について自分で決めても問題はあまり生じないはず
  • 環境の変化度合いが大きい活動はメンバーが自分で決めたほう良い。なぜならいちいちリーダーやチームに判断を仰いでいると、状況変化にスピーディに対応できないため。
  • それぞれのチーム状況を鑑みながら、「誰が何を決めていいのか?」という権限規定に関するルールを定める必要がある

責任範囲のルール(Where)

  • 誰がどの範囲の責任を持つのかを決めなければならない
  • 環境の変化度合いと人材の連携度合いが大きいほど個人ではなくチーム全体に対する責任を負うように責任範囲を定めたほうがよい

評価対象のルール(How)

  • 環境や人の連携度合いによって、何を評価すべきかが変わる。何を見て評価すべきか、というルールを決めるべき。
  • 例えば、人の連携度合いが低いことであればひとりひとりの成果をそのまま評価すればよい
  • 連携度合いが高ければひとりひとりの成果では判断しづらいため、各々のプロセスやアクションで評価すべき
  • 環境の変化が大きい場合は、どのようなアクションをとったかで判断するのは難しく、結果で評価すべき。逆に変化が小さければプロセスでの評価も可能。

確認頻度のルール(When)

  • 評価をどれくらいの頻度で確認するのかを定めよう
  • 環境の変化度合いが大きいか、人材の連携が重要な場合は頻繁に確認しよう

コミュニケーションと感情

  • コミュニケーションは短い方が良いとされるが、感情の観点からは時に長くなってもよい。
  • 「どうせ、しょせん、やっぱり」というチームに根付くネガティブな感情を無くすには、「自分が相手/チームから理解されている」と感じると各々が感じることが重要
  • 自分が理解されていると人が感じるためには「経験」「感覚」「志向」「能力」を理解してもらうことが必要
  • 「経験」と「感覚」を理解するには、横軸に時間、縦軸にモチベーションを取ったモチベーショングラフが有用。経験とそのときの感覚(どう感じたか)を共有しやすい
  • 「志向」は4つのタイプのどれにあてはまるかをチェックしてみよう
  • 「能力」は対自分力、対人力、対課題力のそれぞれがどちらのタイプかをチェック
  • 「志向」と「能力」についてもチーム内で共有して今後のコミュニケーションにいかそう

心理的安全性

  • 心理的安全性が確保されていれば、問題を解決する積極的な発言や行動を引き出すことができる
  • 心理的安全に支障をきたす原因は4つ
    1. 無知と思われる不安 -> 対策:率直に質問しても良いとされる場を設ける
    2. 無能と思われる不安 -> 対策:失敗共有機会を設ける。失敗が悪くない、失敗から学ばないことが悪い、という意識を根付かせる
    3. 邪魔と思われる不安 -> 対策:意見が生まれること自体が良いことという意識を根付かせる。「今の言う意味あった?」は厳禁
    4. 批判的と思われる不安 -> 対策:反対意見機会を設ける。「それは絶対違うでしょ」は厳禁

第四章 Decision(意思決定)の法則

意思決定方法

  • 方法には3つある。
    1. 独裁
    2. 多数決
    3. 合議
  • これら3つは、チーム全体の納得度とスピードがトレードオフの関係になっている。チームによってどれが適切かを選ぶ必要がある

合議

  • 合議は意思決定速度が遅い。つまり、速く結論を出すことが重要になる
  • 何かを決めるときは、まずは選択肢を決めること。なんとなく答えを探すよりスピードが出る。
  • さらに、その選択肢同士を直接比較するのではなく、選択基準と、その基準の優先度を決めれば速く結論までたどり着ける

独裁

  • 圧倒的にスピードが出るが、チームの納得感を増すために情報収集は重要だが、意思決定時に「正しい」決定にこだわるよりも「強い/速い」決定にこだわるべき
  • だいたい意思決定に悩むような事柄は、メリット・デメリットが拮抗している。それならばできるだけ速く決定し、実行に移すべき。早くとりかかれればそれだけ成功する確率も高まる
  • また、独裁を成功させるのに重要なのは意思決定者だけではなく、チームメンバーの協力が大事。チームとして成果を出したければ一度決定されたのなら「たられば」を言うのは効果的ではない
  • チームメンバーが独裁に協力するかどうかは独裁者の特性(影響力)による
  • 影響力は5つに分解できる
    1. 専門性:メンバーに「すごい」と思われる技術や知識がある
    2. 返報性:メンバーに「ありがたい」と思われる支援や関与をしている
    3. 魅了性:メンバーに「すてき」と思われる外見/内面的魅力がある
    4. 厳格性:メンバーに「こわい」と思わせる規律と威厳がある
    5. 一貫性:メンバーに「ぶれない」と思わせる方針と態度がある

第五章 Engagement(共感創造)の法則

エンゲージメントの4P

  • エンゲージメント=チームに貢献しようとするモチベーション
  • エンゲージメントを高める4P
    1. Philosophy(理念・方針)
    2. Profession(活動・成長)
    3. People(人材・風土)
    4. Privilege(待遇・特権)
  • 上記4つのうち、どこに力を入れてどのような色のチームを目指すかを決めよう
  • どのPを伸ばすかによって、メリット・デメリットがある。例えば、Professionで束ねる場合は、どのような仕事をアサインするかといったことには気を使うべきだが、業務外での上司と部下の懇親コストを減らせる傾向にあり、Peopleはその逆になりやすい。

エンゲージメントを生み出す方程式

  • 報酬・目標の魅力 ✕ 実現可能性 ✕ 危機感
  • 実現可能性は、目標を細かなステップに分けることで見えるようになる

感想

  • いろいろためになった。特に心理的安全性を確保するためにどうすればよいか、エンゲージメントはどうすれば高まるのかは参考になった。
  • 影響力の5つの要素は自分の会社のリーダーや社長を分析するのにいいツールだと感じた。
  • 第三章は最初意味不明過ぎた。ルールを決めるからそれを決める際のポイントを4W1Hでという話かと思ったら違った。Who以降は、まず最初に決めるべきルールはこういうのがあるよって話。
  • 第五章は4Pと方程式をすごく密接に本では表現していたがまた別の話では?と思った

Flutterでカラーテーマを動的に変更する

実現したいこと

こんな感じのことをしたい

f:id:nao_666:20190501184509g:plain
カラーテーマの動的変更

説明とかいいからサンプルよこせという方はこちらから。cloneして実行して実際にいじりながら試してみてください。

ライブラリ等を探してみた

とりあえず探してみました。すると、

proandroiddev.com

いい感じの記事を見つけた!しかも配布されている😊

pub.dartlang.org

これで終わった〜😊 と、思ったらちょっと機能が足りませんでした。

このライブラリができることは

  • 動的にbrightness(明暗)を変更できる
  • 変更したbrightnessshared_preferencesに保存される
  • 次回起動時に自動的に保存したbrightnessが適用される

というものでした。しかし、今自分がやりたいことはbrightnessだけでなく、primarySwatchも変更/保存したい、ということだったため少し機能不足でした。

FlutterのThemeに関する補足

ここで急にbrightnessとかprimarySwatchとか出てきて、チョ・マテヨ👩ってなってる人に向けて補足説明をします。自分も最初FlutterでThemeを扱ったとき、どういうクラス構造になっているのか分からず道に迷ってしまいました。ThemeData, primarySwatch, brightness, MaterialColor等のクラスや引数の関係性がだいたい分かっている方は読み飛ばしてOKだと思います。

まず、Flutterで起動時にテーマを指定するサンプルコードを見てみましょう。

return MaterialApp(
  title: 'Sample App',
  theme: ThemeData(
    primarySwatch: Colors.blue,
    brightness: Brightness.light,
  ),
  home: SomePage(),
);

こう書くと、アプリ全体が青い配色になって、背景は白くなります。
上記サンプルコードではthemeというパラメータにThemeDataオブジェクトを渡しているのが分かると思います。これを見ながら語句の解説をしましょう。

解説
ThemeData Flutterのデザインテーマのデータを全て持つ。明るさ、プライマリカラー、アクセントカラーやその他ボタンの色やAppBarの色なんかも持っている
primarySwatch 一言で言えば、「色見本」(swatchは見本という意味)。型はMaterialColor
brightness 明るさ。これもThemeDataのコンストラクタに渡すことができる。lightとdarkしかない。
MaterialColor クラス。dartにはColorというクラスもあるが、それとは別。Colorは1つの色しか保持できないのに対し、MaterialColorは「同じ系統の複数の色」(濃い青、普通の青、薄い青等)を保持できる。

もう少し付け加えると、まずThemeDataのコンストラクタには直接primaryColoraccentColor等が渡せるようにもなっています。しかし、このprimarySwatchを渡しておけばそれらの値はprimarySwatchから取り出されます。

github.com

また、上記説明から分かるとは思いますが、引数primarySwatchの値はColors.blueで、このColors.blueの型はMaterialColorです。つまり、blueと言っても、実際には濃い青から薄い青まで様々な値を保持しています。

ここでThemeDataの特徴なのですが、 brightnessがdarkの場合はprimarySwatchが何であろうとダークテーマになります。先程のソースコードを見てもらえれば分かると思いますが、例えばprimaryColorに関しては

primaryColor ??= isDark ? Colors.grey[900] : primarySwatch;

となっていて、darkのときはColors.grey[900]が適用されるようになっています。primarySwatchがblueであろうとredであろうと関係ないというわけです。

カスタマイズする

見つけたライブラリではうまくprimarySwatchを変更/保持できなかったのでそれができるように変更していきます。見つけたライブラリですが、実は中身はdynamic_theme.dart1ファイルだけという非常にシンプルな作りになっています。

今回はこのライブラリのソースをまるっと自分のプロジェクト内にコピーして好きなように変更していきます。要点だけ説明します。

主な変更箇所

元のソースコードこちら

1. L34 shared preferenceのキー

static const String _sharedPreferencesKey = 'isDark';

brightnessだけを保存するのではなく、テーマ名を保存することにするので、このkeyは変更します

static const String _themeTypeKey = 'theme_type';

2. L67 setBrightnessメソッド

setBrightnessからsetThemeに変更します。

void setTheme(ThemeType theme) async {
  setState(() {
    this._data = themeMap[theme];
  });
  SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.setString(_themeTypeKey, theme.toString());
}

3. L83 loadBrightnessメソッド

loadBrightnessからsetThemeに変更します。

Future<ThemeType> loadThemeType() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  return (ThemeType.of(prefs.getString(_themeTypeKey)) ?? ThemeType.BLUE);
}

フォルダ構成

今回は、dynaic_theme.dartの他、テーマの種類を保持するenumのようなクラスであるtheme_type.dartと実際のテーマの色やbrightnessを定義したapp_theme.dartを追加します。サンプルでは、home画面でテーマを選択できるRadioListTileのリストを表示するので、そのためのtheme_select.dartも追加します。その結果、フォルダ構成は以下のようになります。

lib/
┣ theme/
┃ ┣ app_theme.dart
┃ ┣ dynamic_theme.dart
┃ ┗ theme_type.dart
┣━ main.dart
┗━ theme_select.dart

使い方

使い方は本家dynamic_themeと変わりません。MaterialAppを生成するときにラップしてあげてください。

return DynamicTheme(
  themedWidgetBuilder: (context, theme) {
    return MaterialApp(
      title: 'Flutter Theme Example',
      theme: theme,
      home: ThemeSelectPage(),
    );
  },
);

ピンク濃すぎ問題

さて、ここで問題が発生しました。app_theme.dartに様々なMaterialColorでテーマを定義したのですが、なんかピンク(Colors.pink)が濃い...

f:id:nao_666:20190502215203p:plain:w300
ピンクがなんだか濃い

ということで、独自のピンク色のテーマを定義することにしました。元のピンク色の定義はこんな感じでした。

static const MaterialColor pink = MaterialColor(
    _pinkPrimaryValue,
    <int, Color>{
       50: Color(0xFFFCE4EC),
      100: Color(0xFFF8BBD0),
      200: Color(0xFFF48FB1),
      300: Color(0xFFF06292),
      400: Color(0xFFEC407A),
      500: Color(_pinkPrimaryValue),
      600: Color(0xFFD81B60),
      700: Color(0xFFC2185B),
      800: Color(0xFFAD1457),
      900: Color(0xFF880E4F),
    },
  );

ソース

50の方が徐々に薄くなるようグラデーションをつけて色が定義されています。今回は、最も濃くても700くらいの濃さがあれば十分だと思ったので元の700を900に使って以下のようにあらたなピンク色を定義します。50,100,200が同じ色になってしまっていますが、単なる妥協です😊

static const int _pinkPrimaryValue = 0xFFF06292;
static const MaterialColor softPink = MaterialColor(
  _pinkPrimaryValue,
  <int, Color>{
    50: Color(0xFFFCE4EC),
    100: Color(0xFFFCE4EC),
    200: Color(0xFFFCE4EC),
    300: Color(0xFFF8BBD0),
    400: Color(0xFFF48FB1),
    500: Color(_pinkPrimaryValue),
    600: Color(0xFFEC407A),
    700: Color(0xFFE91E63),
    800: Color(0xFFD81B60),
    900: Color(0xFFC2185B),
  },
);

これで(個人的には)いい感じのピンクになりました。

f:id:nao_666:20190502215203p:plain:w300
もとの濃いピンク
f:id:nao_666:20190502215242p:plain:w300
いい感じのピンク

実際に製品として動くものを見たい

この機能は自分が作った以下アプリに実装されています。(プロフィール→設定→テーマ)

Wishes 〜みんなの夢リスト〜

Wishes 〜みんなの夢リスト〜

Wishes 〜みんなの夢リスト〜

  • Naoya Kimura
  • Lifestyle
  • Free
play.google.com

実際に触ってみたい方は是非〜!

プライバシーポリシー

プライバシーポリシー

画像/メディア/ファイル(USB ストレージのコンテンツの読み取り、USB ストレージのコンテンツの変更または削除)

撮影した画像をストレージに保存するために利用しています

ストレージ(USB ストレージのコンテンツの読み取り、USB ストレージのコンテンツの変更または削除)

撮影した画像をストレージに保存するために利用しています