コピペコードで快適生活

明日使えるソースを自分のために

Go言語の環境構築+モジュール管理

  • Goは2つのモードがある
    • GOPATH モード
      • バージョン1.10までの(過去の)モード。コード管理とビルドをGOPATHで指定されたディレクトリ以下で行う。
      • パッケージはリポジトリの最新リビジョンのみ扱う。
    • モジュール対応モード
      • パッケージをモジュールとして管理する。コード管理とビルドは任意のディレクトリで可能。
      • モジュールはリポジトリのバージョンごとに扱う。
      • GOPATHは以前はプロジェクトソース置き場としての役割もあったが、モジュール対応モードでのGOPATHは依存コードとコンパイル済みキャッシュ、バイナリ置き場としての役割に徹する。
  • パッケージ
  • モジュール
    • モジュール対応モードでは、パッケージをモジュールとして扱う。
    • go.modファイルのあるディレクトリ以下の全てのパッケージがモジュールの配下となる。
  • mainってなに
    • プログラムは何らかの package に属している必要があり、そのうちの1つ必ず main でなければならない。
    • main パッケージの中で main 関数があれば、必ず実行される。
  • 参考

コード

# 最初の設定
$ brew update
$ brew install go

# パスの設定 (~/.zshrc等に記述)
$ export GOPATH=$HOME/go
$ export PATH=$PATH:$GOPATH/bin

# バージョン確認
$ go version
go version go1.16.3 darwin/amd64

# アップグレード
brew upgrade go

# プロジェクトフォルダ作る
cd ~/src/github.com/kinosuke01
mkdir my-cmd
cd my-cmd

# go.modの作成
% go mod init github.com/kinosuke01/my-cmd
go: creating new go.mod: module github.com/kinosuke01/my-cmd

# 処理を書く
$ cat <<EOF > hello.go
package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}
EOF

# 使用されているパッケージを読み込む
# go.mod, go.sum が更新される
# GOPAHT以下にパッケージがインストールされる
go mod tidy

# 実行する
go run hello.go

# コンパイルして実行する
go build hello.go
./hello

クリーンアーキテクチャについて学んだことメモ

全体を通した感想

たぶんこういうことかなと。

  • UIとビジネスルールとDBを疎結合とすること
    • 変更容易性の向上
      • 変更による影響範囲を小さくする
    • テスト容易性の向上
      • テスト対象が依存するオブジェクトをモックに差し替えやすい

レイヤードアーキテクチャ

  • 依存関係
    • UI(Presentation) -> Application -> Domain -> Infrastructure
      • Domain: ビジネスルールを扱う
      • Infrastructure: 技術的詳細(DBへのアクセスなど)を扱う
  • 安定依存の原則に反している
    • 安定しているDomain層が、安定していないInfrastracture層に依存する状態になっている。
  • 感想
    • ビジネスルールとInfrastracture(=DB)が強く紐付いているのであれば、両方とも同じくらい安定していると考えることもできる。
    • その場合は、安定依存の原則に反しているとは言えない。

リポジトリパターンによる依存関係の逆転

  • 依存関係を変える
    • Domain -> DataAccessInterface(を備えたDataAccess) <- Database
      • Domainが依存するのはDataAccessInterfaceを備えたモジュールにだけ。
      • Domainに影響を与えずに、Database以外へのデータソースへの差し替えが可能になる。
  • https://bliki-ja.github.io/pofeaa/Repository/

単一責任の原則に従いDomainを分割

  • Domain層は2つの役割を持っている
    • ビジネスルール
    • データ操作
  • 問題点
    • 互いの修正が影響を与えてしまいがち
    • たとえば、価格の取得が product.price から product.product_pricing.price に変更になった場合、 price を扱うビジネスルールの処理を書き換える必要が出てくるかもしれない。
  • UseCaseInteractor -> Entities
    • UseCaseInteractor: DataAccessを使ったデータの操作とEntitiesを使ったビジネスルール処理の実行を行う
    • Entities: ビジネスルール処理を行う
  • 感想
    • Entitiesに記述する処理は、RailsActiveRecordインスタンスメソッドと対応してそう。
    • UseCaseInteractorに記述する処理は、RailsActiveRecordのクラスメソッドに書く処理と重なることが多そう。
    • Entitiesにあるgetter,setterは多くの場合、テーブルのレコードと対応することになりそう。
      • カラムが増えるたびに、getter,setterを実装する手間がかかりそう。
      • RailsActiveRecordは、UseCaseInteractor,Entities,DataAccessの役割を包括することで、getter,setterを自動生成し、実装する手間を削減していると思われる。

ControllerとUseCaseInteractor

  • Controllerは、parameterの受け取りと、その値に応じたUseCaseInteractorを呼び出しを行う。
  • ControllerはUseCaseInteractorの振る舞い(InputBoundary)に依存する
    • UseCaseInteractorの修正による影響をControllerに与えない
    • UseCaseInteractorの交換を容易にする。
      • Controllerのtestでは、UseCaseInteractorモックを与えることで、容易性や迅速性の向上が見込める。
  • InputDataは、InputBoundaryに与えるデータの型
  • 感想
    • 主な機能はこの辺かな
      • parameterの値チェック
      • parameterの値に応じた条件分岐
        • UseCaseInteractorの呼び出しやエラーハンドリングなど

PresenterとUseCaseInteractor

  • Presenterは、UseCaseInteractorからデータを取得し、表示用に加工してViewに引き渡す。
  • 感想
    • 表示に至るまでのステップは以下の人漆器
      • parameter受け取り → データ取得 → データ加工 → viewへの引き渡し になるので、
    • なので、Controllerとは不可分ではないか

ViewModelとView

  • ViewModel は View のためのデータ構造体。
  • View は ViewModel をレンダリングする。
  • 感想
    • ViewはViewModelの写像という位置づけになりそう。
    • ViewModelはEntitiesとかなり内容が重複しそう。
      • Railsでmodelを直接viewで使えるのは、重複排除が狙いかもしれない。

参考

データソースのアーキテクチャ

データソースのアーキテクチャについて学んだことメモ。

TableDataGateway

RowDataGateWay

ActiveRecord

  • 1クラス=1テーブル、1インスタンス=1レコードに対応する。
  • CRUDの操作だけでなく、ビジネスロジックを実装して使う。
  • レコードとビジネスロジックの結びつきが強い場合は使いやすい。
    • どのオブジェクトに実装すべきメソッドかわからなくなったときは、データモデリングに不備がある可能性がある。
    • たとえば、purchase の実装の場合
      • user.purchase でも、 product.purchased でもなく、purchase_event.create で表現できる。
      • purchase に伴う各種処理は、 create のコールバックで実装すればよい。
  • 単一責任の原則には反している。
    • ビジネスロジックとデータ操作を1つのオブジェクトに詰め込むため。
    • データソースを変更したい(たとえばRDBからRedisに変えるなど)場合、影響がビジネスロジックまで及んで修正が困難になる可能性はある。
  • https://bliki-ja.github.io/pofeaa/ActiveRecord/

DataMapper

  • メモリ内のオブジェクトとデータベースのマッピングを行う。
    • 1オブジェクトに対して複数のテーブルをマッピングするケースもある。
  • オブジェクトとデータベースの構造が1対1対応していない場合に使いやすい。
    • たとえば既存のデータベースの上にアプリケーションを構築する場合など。
  • メモリ内のオブジェクトは、データソースの実態を気にしなくてよくなる。
    • データソースの変更を行ってもビジネスロジックに影響を及ぼすことはない。
      • DataMapperがオブジェクトに提供しているインターフェースを変更しなければ。
  • https://bliki-ja.github.io/pofeaa/DataMapper/

リーン顧客開発の読後メモ

https://www.amazon.co.jp/dp/4873117216 を読んで、いいなと思ったポイントをメモ。

1.顧客開発の目的

  • 顧客が欲しがるものについての誤った思い込みを早く見つける
  • 本当に購入してくれる製品の開発に集中できるように

2.何からやるか

  • チームで時間を作って想定を書き留め、妥当性を検証する。
    • チームメンバーの考えが揃っていないことが多い。
  • 課題仮説を書き出す
    • 顧客タスク をするとき 課題 を抱えている。
  • 仮説詳細
    • 顧客は誰か
    • 顧客の問題は何か
    • 顧客の現在の行動は何か
    • 顧客が進んで購入するソリューションは
    • 顧客にあったソリューションの提供方法は

3.誰と話すか

  • 想定する課題について最も深刻に悩んでいる人を見つける

4.何を学習するか

  • 基本的質問
    • 現在はxをどのような方法で行ってますか?
    • xを行うとき、どのようなツールを使ってますか?
    • もしなんでもできる魔法があれば何をしますか?
    • 前回xを行ったとき、その直前に何をしていましたか?
    • xについて、他にわたしが尋ねるべきものは何かありますか?
  • 顧客が既にしていることは何か
    • いつもはxをどのように行っているか教えてください
    • あなたがxをどのように使っているか、手順を一つずつ確認させてください。
  • 抽象度をひとつあげた質問にすると、革新的な視点を得やすい。
    • ファイルのアップロードと共有方法ではなく、文書を作成し校正が必要になった直近の体験を。
  • 将来ではなく現在に注目する
    • 願望ではなく現実に基づいた質問を。
    • これからxを使うことになると思いますか?(未来形)ではなく、xのようなものを最後に使ったのはいつですか?(過去形)
  • 課題が課題と認識されていない
    • 人は自分が精通しているプロセスに注目する傾向がある。
    • 「目の前のタスクをどのように最適な方法で完了させるか」ではなく「タスクを完了させること」に目がいく。
    • もっとよい選択肢があることを認識してもらう必要がある。

5

  • 会話の流れを保つ
    • 関心がないように思えても、少なくとも1つはフォローアップしましょう。
    • 分析ツール使ってますよ。レポートを作る機能もあるんです。→最近レポートが必要になったのはいつです?→先週です。でも先週は一部が得られませんでした。→それはどのくらいの頻度で起こるんですか?

6.検証済の仮説はどう見えるか

  • 本当に欲しがっているか単なる願望か
    • 現在の行動を観察すること。具体的にどんな行動を取っていたかに注目することで、願望の要素を取り除くことができる。
  • 要約を作成する
    • 流し読みやパターンを見つけるのに便利。メンバーと共有しやすい。
    • ポイントは
      • 仮説をサポートする材料
      • 仮説を棄却する材料
      • 驚きを感じたこと
      • 相手が強い感情を示したもの
  • 仮説が支持されたシグナル
    • 課題をしっかり認識している
    • 課題は解決可能&解決の必要があると感じている
    • 課題解決に投資してきている
    • 課題解決がコントローラブルである
  • 自身を持って以下を答えられるようにする。答えられないなら質問を見直すべき
    • 購入の阻害要因
    • どのように日常に取り入れるか
    • 何を置き換えることになるか
    • 購入しない場合の理由
  • どのくらいの数が必要か
    • インタビュー5回で興奮する人に会える(会えなかったら課題設定が誤っている)
    • 10回でパターンが見え始める(見えなかったら課題の範囲が広い)
    • 話に驚かなくなってきたら十分な数をこなしたと言える

8.既存顧客がいる場合

  • 顧客の言葉こそ売り込みに効く
    • 質問
      • 他の人に勧めますか
      • 誰に勧めますか
      • どのように勧めますか
    • 顧客の言葉をそのままコピーに転用することも
  • 将来実現されるものと誤解されないように
    • 繰り返し伝えること。
      • 学ぶために話していること
      • 会話が探索的であること
      • 不満を述べてもよい
    • 目的は調査ですと繰り返す。あなたの経験をぜひ伺いたい。

9.継続的な顧客開発

  • 継続的に顧客開発するための時間はどう捻出するか
  • カスタマーサポートは情報収集のチャンス
  • 機能追加を要求されたとき
    • なぜそれを望んでいるのかを尋ねること
  • 機能やインターフェースについての不満
    • KISSMetricsでは4つのAをガイドラインにしている
      • 謝る(Apoligize)
      • 非を認める(Admit)
      • 質問する(Ask) ≒ どのように使っているかインタビューする
      • 感謝する(Appreciate)
  • 今週の質問
    • 毎週特定のトピックの質問を1つ選ぶ
    • 末尾に質問を追加する

OS起動時に自動でディレクトリやファイルを作成する

たとえば、CentOS7では、/var/run/* がシャットダウン時に削除されるけど、OS起動時にはディレクトリ作っておいてほしいケースとかで使う。

設定ファイル置き場

/etc/tmpfiles.d/*.conf

記法

# ディレクトリがなければ作る
d /var/run/my_app 755 root root

# ディレクトリがなければ作る
# ディレクトリがあれば中身を空にする
D /var/run/my_app 755 root root

# ファイルが存在しなければ作成する
f /var/run/my_app/data.txt 644 root root

参考

kubectlでpodのログを確認するまで

context、namaspace、deploymentがわかっている状態からどうやって確認するかメモ

contextの確認・設定

設定は ~/.kube/config に書いてある。

# 一覧表示
kubectl config get-contexts

# 切り替え
kubectl config use-context my-context

# 現在のcontextの表示
kubectl config current-context

namespaceの確認

同一の物理クラスター上で動作する複数の仮想クラスタhttps://kubernetes.io/ja/docs/concepts/overview/working-with-objects/namespaces/

# namespaceの一覧表示
kubectl get namespace

Deployment・ReplicaSet・Podの確認

  • Deploymentによって、複数のPodのセット(ReplicaSet)が作成される。
  • Deployment ⊃ Replicaset ⊃ Pod という関係。
  • ReplicaSetの名前は [Deployment名]-[ランダム文字列]
  • Podの名前は [ReplicaSet名]-[ランダム文字列]
  • Podの名前から、どのReplicaSetやDeploymentに属しているかがわかる。
# Deployment 一覧表示
# --namespaceでnamespaceの指定ができる
kubectl get deployments --namespace=my-space

# Deployment 1件表示
kubectl get deployment my-deployment --namespace=my-space

# ReplicaSetの確認
kubectl get rs --namespace=my-space

# Podの確認
kubectl get pods --namespace=my-space

Podのログを確認する

https://kubernetes.io/ja/docs/reference/kubectl/cheatsheet/

kubectl logs my-pod                                 # Podのログをダンプします(標準出力)
kubectl logs -l name=myLabel                        # name=myLabelラベルの持つPodのログをダンプします(標準出力)
kubectl logs my-pod --previous                      # 以前に存在したコンテナのPodログをダンプします(標準出力)
kubectl logs my-pod -c my-container                 # 複数コンテナがあるPodで、特定のコンテナのログをダンプします(標準出力)
kubectl logs -l name=myLabel -c my-container        # name=mylabelラベルを持つPodのログをダンプします(標準出力) 
kubectl logs my-pod -c my-container --previous      # 複数コンテナがあるPodで、以前に作成した特定のコンテナのログをダンプします(標準出力)
kubectl logs -f my-pod                              # Podのログをストリームで確認します(標準出力)
kubectl logs -f my-pod -c my-container              # 複数のコンテナがあるPodで、特定のコンテナのログをストリームで確認します(標準出力)
kubectl logs -f -l name=myLabel --all-containers    # name-myLabelラベルを持つすべてのコンテナのログをストリームで確認します(標準出力)

(補足)ログインする

kubectl exec -it my-pod -- bash

プロセスが掴みっぱなしの削除済ファイルを取り出す

ファイルを作成して、lessで掴む

$ echo 'dummy data' > example.txt
$ less example.txt

別ターミナルで、掴んだファイルを消す

$ rm example.txt

削除済のファイルを掴んでいることを確認できる

$ ps a | grep less
23249 pts/14   S+     0:00 less example.txt
23290 pts/15   S+     0:00 grep --color=auto less

$ lsof -p 23249
COMMAND   PID       USER   FD   TYPE DEVICE  SIZE/OFF     NODE NAME
# 略
less    23249 kinosuke01    4r   REG  253,1        11 46213308 /home/kinosuke01/example.txt (deleted)

/proc/${PID}/fd/${FDの数値} 配下に掴んでいるファイルが有ることを確認する

$ ls -la /proc/23249/fd/4
lr-x------ 1 kinosuke01 xxxxx 64  4月 22 17:51 /proc/23249/fd/4 -> /home/kinosuke01/example.txt (deleted)

cpコマンドで救出できる(-aオプションをつけると駄目らしい)

$ cp /proc/23249/fd/4 ~/exmaple.saved.txt
$ cat ~/exmaple.saved.txt
dummy data

参考

https://www.itmedia.co.jp/enterprise/articles/0611/30/news007.html