nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

Google SRE Book と Go

www.amazon.co.jp

これを読んでわかったが Google は人間を信頼性の低いパーツだと思っている。

悪い意味ではない。
人間は動作が不安定で簡単には変えが効かずコストが高いので大切に扱いつつ、できるだけ人間の手が必要ない自律したシステムを作ることでうまく巨大なシステムを運用しようとしている。

大切に扱っているという部分が面白く、たとえば障害対応は持ち回り制にしましょうとか、24時間対応できるようにタイムゾーンを分けて複数のチームで障害対応を担当しましょうとか、障害対応中であっても引き継ぎして帰れるように状況は共有しながら対応しましょうとか、障害報告書には誰かを責めるような書き方をしないようにしましょうとか、当たり前っぽいけど合理的でシステムを運用したことがあれば自分もこんな環境が欲しかったと思わせるような内容が書いてある。

システム運用には「手動・自動・自律」というフェイズがあるとしており、手動は完全に人間が運用するもので、自動はスクリプトなどにより作業を自動化したもの、自律はシステム自身が状況を監視して適切な運用をするようにしたものだ。
巨大なシステムを手動で運用するのは無理がある。手動や自動だとシステムの大きさに合わせて人を増やす必要があるが人はそう簡単に増やせるものではない。信頼性を上げるためだけではなくシステムを大きくするためにも人の手を離れた自律した状態にするということは必要になるのだそうだ。

Google は人間の弱さを認めてそれをいかに克服するか、あるいはいかにコントロールするかということをやっている。
その観点から Go について見ると面白い。

Go は仕様の小さい言語だ。
クラスは無いし継承もない。例外もないしジェネリクスもない。
この機能があると便利だなと思うことは実際あるが、この機能がないと絶対実装できないと思うことはあまり無い。
むしろある処理を実装するのに一つの方法しか用意していないという状態は、書くのにも迷わないし誰が書いても同じようになり読みやすいのでストレスが小さくなる。

複数人で開発をしていてもやっとするのは微妙に不適切な実装をされたときだ。
一応それでも動くけれどもそれただ最近おぼえたであろうその機能を使いたいだけなんじゃないの?もっと単純に実装できんじゃないの?みたいなときは指摘しづらいし指摘しても微妙な空気になったりすることがあるのであまり嬉しくない。
言語仕様が小さいとそもそもそういうブレが少なくなるので嬉しい部分がある。

また、言語仕様が複雑だとその言語で作られたソフトウェアも複雑になりやすい。
もちろんそれは実装する人次第ではあるけれど、おれはいいけどおまえは使いこなせないからこの複雑な機能使うなとかは普通は言えない。
コーディング規約で縛って機能を制限するとかもできると思うが、それならそもそも仕様が単純な言語を使ったほうが簡単だと思う。

例外とか使っていていつも使いこなせている気になれなくてこれでいいのかなーとか不安な気持ちだったし、継承とか他の開発者が適当に使っていてつらい気持ちになったことが何度もある。

いろいろな機能がある方が書きやすいのは当然だが、Go は「どうせ複雑なものは人間には扱いきれないでしょ」っていうことで人間がコードを書きやすくなることよりも機能を絞ってソフトウェアの信頼性を上げることを選んでいるのだと思うし、自分もそれに心地よさを感じているところをみると自分で思っているよりも大したことないんだとわかって謙虚な気持ちになったりした。

Macbook 初期設定メモ 2017

公式からダウンロードしてインストール

brew でインストール

その他

試したけど見送ったもの

  • fish
    • 普通に使えそうだったけど gvm の起動スクリプトが文法エラーになったので深追いしないで見送り

Angular で JSON を POST で送信しようとすると空になる

はじめに

  • Angular で公式ドキュメント の通りに JSON データを POST で送信しようとすると Body が空になるので対策をメモ

環境

  • Angular 4.3.5

公式ドキュメントのコード

  • このとおりだと Body が空になる
const body = {name: 'Brad'};

http
  .post('/api/developers/add', body)
  // See below - subscribe() is still necessary when using post().
  .subscribe(...);

対策したコード

  • JSON.stringify すると正常にデータが POST できる
const body = JSON.stringify({name: 'Brad'});

http
  .post('/api/developers/add', body)
  // See below - subscribe() is still necessary when using post().
  .subscribe(...);

メールアドレスとウェブサイトを Google のサービスのみを使って用意する

はじめに

  • アプリを公開するため問い合わせ用のメールアドレスとウェブサイトを用意することにした
  • メールアドレスの用意のためにメールサーバーは管理したくないので Gmail が使えて独自ドメインが使える G suites を使う
  • ウェブサイトは GAE/Go を最近使っていて慣れているので静的ページのみだが GAE を使ってみる

独自ドメインのメールアドレスをつくる

  • Gmail などが独自ドメインで利用できる G suites に契約する
  • 1 アカウントで最安プランで月 600 円、1 年まとめ払いで月 500 円
  • ドメインも一緒に購入できて “.com” で年 1000 円
    • 実際のドメイン管理者は Google ではなく eNom
    • 値段はお名前.comと同じくらいで eNom で直接買うより何故か安い
    • 購入後に eNom 側の管理画面を使って DNS のカスタム設定もできる
  • 購入後にアカウントの設定からメールのエイリアスも登録できる

独自ドメインのウェブサイトをつくる準備をする

  • 作成したメールアドレスで Google Cloud Platform に登録する
    • いまだと新規契約で 300 ドルまでの無料枠が使えた
  • GCP でウェブサイト用のプロジェクトを作成する
  • Google App Engine をつかってウェブサイトをつくる
    • 静的ページのみでも GAE を使うと独自ドメインでの公開が楽
    • 静的ページのみならインスタンスの起動時間あたりの使用料は発生しない
    • GAE の設定ファイルだけで簡単なルーティングをしてくれるので Google Cloud Storage とかに直接静的ファイルを置くよりも便利
  • Google Site Repositories でウェブサイトのソースコードを管理する
    • ウェブサイト用のプロジェクトで GSR のレポジトリをつくる

ウェブサイトを作る

設定ファイルを用意する

  • “/” で “index.html” を表示
  • それ以外は “404.html” を表示
  • それだけだとデプロイ時にエラーになるので参照されない go ファイルの実行パスを追加
runtime: go
api_version: go1

handlers:
- url: /
  static_files: index.html
  upload: index.html
- url: /.*
  static_files: 404.html
  upload: 404.html
- url: /.*
  script: _go_app

HTML ファイルの用意

  • 任意で

Go ファイルの用意

  • 参照されないが置いておかないとデプロイできないので何もしないファイルを置いておく
package main

import "net/http"

func init() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // no op
    })
}

デプロイ

gcloud app deploy app.yaml --project [PROJECT_ID] -v [VERSION]

さいごに

  • 独自ドメインとメールアドレスの方は探せばもっと安いものはありそうな気がするがとりあえず慣れているので Gmail 便利。
  • ウェブサイトの方は使わない Go ファイルを置いたりするのがいけてないが、よっぽどのことがない限り無料枠で収まってれると思うので悪くない気がする。

Unity の UnityEditor.BuildPipeline:BuildAssetBundles で出たエラーと対策

前提条件

  • Unity 5.6.1f
  • UnityEditor.BuildPipeline:BuildAssetBundles で Asset Bundle をビルドしたらエラーが発生した

エラー内容

  • ポップアップで “Build failure Internal error: Target platform mismatch”
  • コンソールに “Menu Edit/Graphics Emulation/OpenGL ES 3.0 can’t be checked because it doesn’t exist” とエラー表示

対策

  • Unity 5.6.1f から最新の Unity 5.6.2f にアップグレードしたらエラーにならずに正常に Asset Bundle のビルドができるようになった

参考URL

https://forum.unity3d.com/threads/got-an-error-when-building-assetbundles-target-platform-mismatch.476663/

ユースケース駆動開発実践ガイドまとめと感想

はじめに

感想

  • ウォーターフォール的なちゃんと設計ドキュメントを作ってから実装する、みたいな流れで開発をしたことがなかったので勉強になったし、ユースケースの作り方なんかはためになった
  • これをそのまま実践するかというとしないと思うが、選択肢として堅いやり方を知っておきながら柔らかいやり方と使い分けていけるようになれればいいかなと思う

簡単なまとめ

  • 全体を通して ICONIX(アイコニクス)プロセスという手法を使ったソフトウェア開発について書かれている
  • ざっくりまとめると、要求を、ドメインモデル、ユースケースロバストネス図、シーケンス図、コード、と変換していくことで、要求漏れがなく手戻りが少ない開発ができる、みたいなことだと理解
  • 以下各章ごとに順にまとめ

第1章 ICONIXプロセス

  • 全体の大まかなまとめ
  • 全部読んでからならここだけ読めばなんとなく復習できるかも

第2章 ドメインモデリング

  • 静的モデルを一番初めに定義しておき、後の工程で曖昧さのない用語を利用する

感想

  • エリック・エヴァンス本で言うユビキタス言語のことか
  • エリック・エヴァンス本でドメインモデルというと図のことではなく振る舞いなども含めた概念を指すと思うので同じ言葉だが別のものを指しているはず

第3章 ユースケースモデリング

  • 要求からユースケースを作っていく
  • ユースケースとは「AはBをする、次にCはDをする」という叙述的なものになる
    • ユーザーがログインする場合のユースケースの例は「システムはログイン画面を表示する。ユーザーはユーザー名とパスワードを入力してログインボタンを押す。システムはユーザー名とパスワードをチェックする。ユーザーはシステムにログインする。」といったもの
  • ユースケースは基本コース(正常系)と代替コース(異常系)すべてを網羅すること
  • ユビキタス言語を使用して記述されていること
  • 「ログイン画面を表示する」というようにGUIの具体的なパーツ名を使用して記述されていること
  • 必要であればドメインモデルを更新する

3つの魔法の質問

  • ユースケースを書くときには、「何が起きるか?」「そして何が起きるか?」「他にどのようなことが起きそうか?」という質問を繰り返して正常系異常系すべてのケースをあぶり出していく

第4章 要求レビュー

  • ドメインモデルとユースケースが要求を満たしているか顧客と共にレビューを行う
  • 必要なら紙芝居やモックやプロトタイプを作って説明を行う

第5章 ロバストネス分析

感想

  • ロバストネス図を作ることで予備的な設計が行われ、UIやドメインや処理の不足や用語のブレなどがあらかじめ浮き彫りになってくる
  • 最近 twitter で流れてきた、先の工程に進むと前の工程のアラが見えてくる法則を逆に利用してはやめに先の工程に進んでミスを潰していくという戦術なのかも
  • オブジェクトでもコントローラでもない、間の線に書かれた文字の意味がわからない
    • なんとなくユーザーの振る舞いは線上に書いている気がする
    • ユーザーの振る舞いでもコントローラになっているものもある
    • 粒度の問題?
    • たぶん説明がないのでロバストネス図について理解が曖昧になっている

第6章 予備設計レビュー

第7章 テクニカルアーキテクチャ

第8章 シーケンス図

  • ロバストネス図をシーケンス図に変換する
  • 正常系も異常系も同じシーケンス図上に記述する
  • ロバストネス図上では各コントローラについて誰が主体になって行っているかが記述されていないので、シーケンス図を使って処理の主体をはっきりさせてオブジェクトとメソッドを定義していく
  • 活性区間(線上の長方形、オブジェクトのライフタイムを表す)は利用しない
  • 必要であればロバストネス図を更新する

第9章 詳細設計レビュー

  • シーケンス図を開発者のみでレビューする
  • シーケンス図とユースケースの割り当てができてるかや、適切な属性と操作が割り当てられているかなどを確認する

第10章 実装

  • ここから具体的に Spring Framework を使って具体的に実装していく
  • 汎用的に使えそうな内容としては、設計をそのまま実装しなさい、コーディング中につまったら設計から見直しなさい、設計とコードを常に動悸させなさい、コメントを書きすぎてはいけません、正常系だけでなく異常系も書くのです

感想

  • ここから先は Spring Framework についての具体的な話になっており流し読みしたくらいなので省略

GAE/Go 環境で echo が実行できない問題

問題

  • GAE/Go 環境で echo を使ったアプリケーションを goapp serve で実行しようとすると以下のエラーが発生して実行できない
2017/01/16 16:08:42 go-app-builder: Failed parsing input: parser: bad import "unsafe" in github.com/valyala/fasttemplate/template.go from GOPATH

原因

  • echo が依存している fasttemplate でエラーが出ている
  • Issuesは出ている
  • 修正パッチのPull requestも出ている

対策

  • Pull request がマージされるのを待つ
  • 待てない場合は変更内容をローカルの fasttemplate のソースコードに適用する。手元では動いた。