Go言語の環境構築+モジュール管理
- Goは2つのモードがある
- パッケージ
- モジュール
- モジュール対応モードでは、パッケージをモジュールとして扱う。
- go.modファイルのあるディレクトリ以下の全てのパッケージがモジュールの配下となる。
- mainってなに
- プログラムは何らかの package に属している必要があり、そのうちの1つ必ず main でなければならない。
- main パッケージの中で main 関数があれば、必ず実行される。
- 参考
- https://zenn.dev/spiegel/articles/20210223-go-module-aware-mode
- pecoはGoでコマンド作るときの参考になりそう。
コード
# 最初の設定 $ 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へのアクセスなど)を扱う
- UI(Presentation) -> Application -> Domain -> Infrastructure
- 安定依存の原則に反している
- 安定しているDomain層が、安定していないInfrastracture層に依存する状態になっている。
- 感想
- ビジネスルールとInfrastracture(=DB)が強く紐付いているのであれば、両方とも同じくらい安定していると考えることもできる。
- その場合は、安定依存の原則に反しているとは言えない。
リポジトリパターンによる依存関係の逆転
- 依存関係を変える
- Domain -> DataAccessInterface(を備えたDataAccess) <- Database
- Domainが依存するのはDataAccessInterfaceを備えたモジュールにだけ。
- Domainに影響を与えずに、Database以外へのデータソースへの差し替えが可能になる。
- Domain -> DataAccessInterface(を備えたDataAccess) <- 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に記述する処理は、RailsのActiveRecordのインスタンスメソッドと対応してそう。
- UseCaseInteractorに記述する処理は、RailsのActiveRecordのクラスメソッドに書く処理と重なることが多そう。
- Entitiesにあるgetter,setterは多くの場合、テーブルのレコードと対応することになりそう。
- カラムが増えるたびに、getter,setterを実装する手間がかかりそう。
- RailsのActiveRecordは、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 をレンダリングする。
- 感想
参考
データソースのアーキテクチャ
データソースのアーキテクチャについて学んだことメモ。
TableDataGateway
- インスタンスがテーブル内のすべての行を操作する。
- SQLはこのインスタンス内に閉じる。
- https://bliki-ja.github.io/pofeaa/TableDataGateway/
RowDataGateWay
- 1クラス=1テーブル、1インスタンス=1レコードに対応する。
- CRUDの操作を行うのみで、ビジネスロジックは載せない。
- 要はActiveRecoredからビジネスロジックを差し引いたもの。
- https://bliki-ja.github.io/pofeaa/RowDataGateway/
ActiveRecord
- 1クラス=1テーブル、1インスタンス=1レコードに対応する。
- CRUDの操作だけでなく、ビジネスロジックを実装して使う。
- レコードとビジネスロジックの結びつきが強い場合は使いやすい。
- どのオブジェクトに実装すべきメソッドかわからなくなったときは、データモデリングに不備がある可能性がある。
- たとえば、
purchase
の実装の場合user.purchase
でも、product.purchased
でもなく、purchase_event.create
で表現できる。purchase
に伴う各種処理は、create
のコールバックで実装すればよい。
- 単一責任の原則には反している。
- 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)
- KISSMetricsでは4つのAをガイドラインにしている
- 今週の質問
- 毎週特定のトピックの質問を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