Photoruction工事中!

Photoructionの開発ブログです!

Atomic Design

エンジニアの秋山です。

プロジェクトのコンポーネントの管理にはある程度共通の認識を持ちたいので、Atomic Design を採用しています。

Atomic Design について

Atomic Design はアメリカの Web デザイナーである Brad Frost 氏が提唱したデザインシステムの設計方法です。

https://atomicdesign.bradfrost.com/

Atoms、Molecules、Organisms、Templates、Pagesという5つのレイヤーにわけて管理しましょうというものです。

具体的に実装していく上で、デザインシステム設計なので、コンポーネントの実装にそのまま当てはめることができない場面がでてきます。

今回は、Nuxt3でのプロジェクトでの管理としていく上での運用のルールを設計しました。

Templates、Pagesに関してはそれぞれ、layouts、pagesという概念が存在しますので、それ以外をコンポーネントとして管理することにします。

運用ルール

Atoms、Molecules、Organismsについては、以下のシンプルなルールを適用します。

ドメイン依存とは、プロジェクト固有や、フレームワーク固有のものを利用する場合。

コンポーネント依存というのは他のコンポーネントを利用しているかどうかというものです。

実際に運用する上で出てきた時のQ&A


条件としては必要十分かと思いますが、状況で悩む場面がでてくるので、具体例を以下に上げます。

Q.コード量が多くなったけど、他のコンポーネントに依存していないのでMoleculesですか?

Moleculesです。ただ、コード量が多いと思うのであれば、Atomsに分割できるところがないか検討ください。

Q.VuetifyのようなUIコンポーネントを利用したいのですが、利用したコンポーネントはOrganismsでしょうか?

Vue3のコンポーネントであるならMoleculesに含めても問題ありません。Vue3以外を含む場合はOrganismsにしてください。

Q.Composition APIを利用する場合はOrganismsでしょうか?

ref watch といったComposition APIはVue3の機能になるので、Molecules、Atomsでも大丈夫です。

Q.Atomsで Nuxtの useState を利用したいのです。

Nuxtというフレームワークに依存しているのでOrganismsにしてください。コード量やサイズは関係なく、Organismsです。

Q.ファイルがいっぱいになって管理がしにくいです。

適宜サブディレクトリを作成して管理してください。

Atoms、Moleculesであれば、UIフレームワークの分類が参考になるでしょう。

Organismsはプロジェクトの機能単位でつけてください。

common は使わないでください。

「ぜんぜん違うじゃん!」 『……』 「言ったよね!?シンプルなルールで必要十分ですって…なのに、この結果は何!」

最後に

実際のところ、Atomic Designは昔持て囃されましたが、運用つらい、そこまで必要としていないと代替がでないまま廃れ気味ではありますが、とっかかりとしては悪くないと思います。

他のプロジェクトで再利用しないのであれば、Molecules、Atomsまでわけなくてもと思いますが、後でデザイン変更や管理するときに便利だったりします。

やりすぎないことが大事で、手段が目的にならない程度にみんなが納得できるルールづくりが大事かなと思います。

よきよいコーディングライフを。

株式会社フォトラクションでは一緒に働く仲間を募集しています

【入社エントリ】 PMとしてフォトラクションに転職した経緯

こんにちは、フォトラクションでPdMをしている平塚です。2023年8月に入社して、4ヶ月が経ちました。

今回は僕自身が「なぜ、フォトラクションを選んだのか」という点について記事を書いていこうと思います!プロダクトマネージャーやデザイナーの方々向けになると思いますが、社内の雰囲気やカルチャーを少しでもお伝えできたらと思います!

入社した理由

1. Mission, Visionへの共感

製造、小売といった業界でPdMやUXデザイナーとしてのキャリアを積み、今後のチャレンジに関して考えていました。その中でフォトラクションの選考を受け、建設業は多様な役割の人たちが関わり、業務フローも煩雑性が高いと聞きました。そのように複雑だからこそ、やりがいのあるテーマだと思い、興味を持ちました。例えば図面作成ひとつとっても、様々な専門性を持った設計士が関わったり、営業が施主プレゼンに用いたり、現場監督や協力会社の職人さんが図面を閲覧し現場作業を行ったりします。このように多数の職種の方が関わっているため、皆んなに適したUXを作る難易度が高いです。また、書類作成も膨大な量の書類を作成し、種類も様々あります。システム化するにあたってそれらを効率よく運用できる仕組みが必要です。こういった複雑な問いを紐解いて、最大限にシンプルでしっくりくる機能を作っていくことに、今までのキャリアを活かしていけると思いましたし、チャレンジングなテーマだと思いました。 また、建設業界のDXという大きなテーマに挑戦していける点も魅力に感じました。世界で1,400兆円のマーケットと言われる、建設産業。ITの活用も実はとても盛んであるものの、そのポテンシャルを最大限発揮できている状態ではありません。業界の課題を本質的に解決できるプロダクトを創り、建設の世界を限りなくスマートにしていきたいと思いました。

2. 働く人の素直さ

粗削りでも良いので「えいや」でどんどん形にしていく。他の人にも伝えながら、ブラッシュアップしていく。物事を前に進める上でとても重要だと思っています。それには、スポンジのように色々なものを吸収できる素直さ&困難なことがあっても前向きに乗り越えられることが大切だと思います。そういった素直さや前向きさを持った方々と働き、一緒に自身も会社も成長させていきたいと考えました。

フォトラクションの選考で営業、人事担当者、開発と多くの社員とお話をした際、ありのままに事業や組織がこういう状況であることを伝えてくれました。率直かつ誠実で、気持ちよく仕事ができるのではないかと感じました。あと、各メンバーが何事にも楽しむ姿勢を持っていると思います。会話の中でアイデアが広がり「こんなことできると良いね!」とテンションが上がってくる瞬間がよくあります。スタートアップなので大変なこともありますが、一緒に楽しみながら高い壁を乗り越えていきたいと思いました。

フォトラクションで働く魅力

建設業界に関わりがない方には、弊社の事業領域はとっつきにくいのではないかと思います。私自身、建設業界は初めてであるため、毎日学ぶことばかりです。弊社には業界知識が深いドメインエクスパートが多く在籍しています。プロダクトを開発する上でユーザーの業務フローに沿ったUXを構築する必要があると思いますが、彼らの声はとても参考になります。さらに、みんなが毎回丁寧に熱量高く答えてくれますので、顧客解像度を高められ仮説の解像度を上げていけると思います。

また、弊社ではアプリケーション(SaaS)、オペレーション(BPO)、マネジメント(MSP)を各フェーズ(設計、調達、施工、維持管理、経営)で標準化し、産業全体の生産性向上を目指しております。建設業界はバリューチェーン重厚長大であり、弊社で提供できる価値も未だ一部分です。「建設の世界を限りなくスマートにする」というミッションを達成するために、まだまだやらなくてはいけないことが多いです。そういったフェーズだからこそ、目指すべきプロダクトの未来を自ら創っていけるという点も魅力的だと思います。

まとめ

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

少しでもPdMやデザイナーの方々にとってフォトラクションで働く魅力が伝われば嬉しいです。

フォトラクションのMissionやVisionに共感いただき、会社の成長を牽引していきたい人と是非一緒に働きたいです!

株式会社フォトラクションでは一緒に働く仲間を募集しています

エンジニアになってから、エンジニアがしなそうな事をしてみた。

はじめまして、CREチームのトヨカズです!

CREの業務にも徐々に慣れてきて、プロダクトの事も少しずつわかるようになってきた9ヶ月目。今回は、この半年程度でCRE以外の業務&プライベートでやってきた他エンジニアがしなそうなことをやったので記事にまとめてみました🕺

そこで感じたことや学んだこと、気づきなどを振り返りながらつらつら書いてこうと思いますので、気になる方はぜひ見てください!

CREの業務について気になる方はこちらをチェック↓↓↓

kojichu.photoruction.com

CREチームについて気になる方はこちらをチェック↓↓↓

※この記事では、エンジニアとしての業務以外の事とプライベートで取り組んだ事について記載しています。技術に関する内容ではないので、予めご了承ください🙇‍♂️

業務において

自分の部署/他部署の方と積極的にコミュニケーションをとる


入社してからまず初めにやった事は、自分の部署/他部署の人とコミュニケーションを取る事でした!具体的な行動としては以下2つ。

  • 社内のイベントに積極的に参加
  • プライベートで、飲みのお誘い ※一滴も飲めないけど

理由としては、

  • 自分が所属する会社の雰囲気をより深く知るため
  • 今までの会社の変遷を知ること

上記2つが建前的な理由として挙げられますが、何よりも「一緒に働く仲間がどんな人達なのかもっと知りたい」というただの好奇心です(笑)

色んな部署の方とコミュニケーションを取ることで、それぞれの視点から見た組織が浮かび上がってくるので、異なる視点を知れる楽しさがあります!他にもビジネスサイドの話を聞くことで、ユーザーさんがどんなものを求めていて、プロダクトがどんな使われ方をしてるのか知ることができたり、自分の部署にいるだけでは知り得ない情報を拾えたりするので、意外とおすすめだったり?※後はシンプルに楽しい!これに尽きます。笑

SNS運用


転職活動中、フォトラクションではどんな人が働いているのだろうと思い、SNSWantedlyなどで検索してたのですが、インタビュー記事などは見つかるものの人物のキャラクターまでを知る事はできず、実際入るまでどんな人が働いているのかはわからずでした。そんな体験から、「もっとフォトラクションの中の人を知ってもらおう」ということで、SNS運用チームを発足!

「これをやりたい!」という願望から、具体化するまでのスピード感を体験し、これが「スタートアップか」と思った記憶があります(笑)

本業と折り合いをつけながら運用してる関係もあり、meetingの時間が限られるので話す内容は事前に決めて、要点を絞ることでゴールを見失わないかつ生産性のあるmeetingを心がけています。

アドカレ運用


毎年、クリスマスまでのカウントダウンとしてアドベントカレンダーを実施してますが、2023年は自分が運営担当をしてました!

事前のタイムスケジュール組みやアポどりなどその他コミュニケーションを含む面で、始まる前に色々苦労しましたが、なんとか軌道に乗せることができてるので一安心です。(終わるまで油断はできない)

ただ学びも多くあり、タイムスケジュールしかり、工数管理しかり、何より他のチームの方々と交流できた事がいい経験でした🥺

ユーザーヒアリングのため、現地に足を運ぶ


ユーザー様の元へ足を運び、実際にフォトラクションがどのように使用されているのかを目で見る事ができ、リアルなユーザー体験を知る事ができました。また、仕様について「こういった機能があるといい」など改善要望も聞く事ができたので、その点も今後CREという立場を活かしながらユーザー様からの声を反映させられればと思います!

プライベートにおいて

他社のイベントに参加しまくる


友人から誘われたイベントだったり、自分で見つけたイベントに足を運びひたすら横のつながりを増やしていました!他社の方と絡むことで、自社以外の取り組みを知れたりするのでとても参考になります。また、企業・組織・ポジション・職種によって視野・視座・視点が全く異なるので、そういった意味でも思考やマインドがどんどん広がっていくのでとても楽しいです💡

情報に疎い僕ですが、こういった取り組みをしてると一次情報が勝手に入ってきたりするので、そういった意味でも、オススメアクションの一つです!

エンジニアコミュニティで、輪読会実施


いざ技術書を一人で読み進めようと思っても、難しい本だと中々捗らず…

でも、他の人とやれば読み進めながら議論し合い、情報を持ち寄ることで補完ができるのでは?と考え、とりあえず声をかけて輪読会がスタート😂※適当

1冊終えた感想としては、やはり一人でやるより効果が高い。自分一人だと調べきれなかったり、理解につまづく事があるので、その辺をいい感じに補完し合えるのが輪読会の良さだなと思いました!また、人に伝えるためには自分が理解しないといけなかったりするので、インプット・アウトプットの両方で、効果が期待できると思います。

調査タスクや仕様の確認などをひたすらドキュメント化


言語化したものを可視化しないと理解が追いつかないことが多々あるので、ひたすらドキュメント化を行なっていました。相手に伝える手段としても使いやすく、自分の理解の助けにもなるので、個人的には効果を感じています。同じようなタスクを振られた際に振り返れる情報があるのは時間の短縮や改善も期待できるので、引き続きやっていきたいです!

未経験エンジニアへのキャリアアドバイス


キャリアアドバイザーをしていたこともあり、時々未経験エンジニアや現役エンジニアからキャリアについての相談を受けたりします。自分以外のキャリアを知ることは自分のキャリアを構築していく上でとても重要なので、キャリアチェンジしてからもキャッチアップを積極的に行なっています。

読書の習慣化


エンジニアになる前から読書(技術書含む)はちょいちょいしてましたが、どうせ技術書をたくさん読むならそもそも読書を習慣化してしまおうと思い仕組み化。技術書を除くと、ビジネス書・自叙伝・思考系・マインド系などジャンルは様々。とりあえず気になった本を図書館で借りて、2週間で1冊借りてくるのと、自分で購入した本、会社で借りた本などを適当に乱読。※技術書以外は、基本ただの趣味。

結果、引きこもりの完成です🙄月に4-5冊読めるようになったので、よしということで…

まとめ

他にも業務内容やプログラミング言語のキャッチアップなどありましたが、普通にやりそうなことだと思ったので、今回は取り上げませんでした。

1つ気づいたことは、多くの人やコミュニティに関わることで得られる情報の量が違うなと感じました!思わぬところで、思わぬ繋がりもあったりするので、個人的には対外的に交流することは続けていこうと思います!

株式会社フォトラクションでは一緒に働く仲間を募集しています

Fishシェルを使いましょう

Fish(フィッシュ・シェル)はFriendly Interactive SHellの略で、UNIX系システムのシェルであり、UX(ユーザーエクスペリエンス)に長けたシェルです。そのため他のシェルに比べて仕事が効率的に出来ることが多いです。

FishのASCIIロゴ
FishのASCIIロゴ

Linuxディストリビューションの兼ね合いでBashシェルを使用する方は多いかもしれません。そこからもっと使い勝手のいいZshに移った方や、macOSのアップグレードでデフォルトシェルがZshを使用されている方はいらっしゃると思いますが、それもオワコンと断言できます!

Fishはホームページには90年代のためのシェルと書いてありますが、私は21世紀のシェルであると盲信しています。他のシェルを使用する中でFishを使い始めたらもう手放せません。

BashZshの時にコマンドを打つたびにmanページ(ターミナルからアクセスできるUNIX系マニュアルコマンド)を読んだり、ググったりしていましたし、なんとかcompletionのパッケージをインストールしたりしていましたが、Fishではそれをきにすることなく、manページから自動的に解析し、コマンドの先頭文字を書きながらTabキーを押すことでコマンドの説明やオプションやサブコマンドをわかりやすい色使いで、表示してくれます。過去に入力したコマンドを薄いグレー色で表示し、キーを押すと保管してくれます。シンタックスハイライトも美しいですし、右側のプロンプトの設定などもできます。

Fishでのlsで始まるコマンド補完挙動
Fishでのlsで始まるコマンド補完挙動

Fishでのlsコマンドのオプション補完挙動
Fishでのlsコマンドのオプション補完挙動

Zshでもそんなことができるぞ」とおっしゃる方はいらっしゃるかもしれませんが、これはいわゆる「Out of the Box」(何のカスタマイズもない)Fishの振る舞いです。

では導入方法を見ていきましょう:

Fishを導入

インストール

各プラットフォームのインストール方法は公式ホームページから確認できます。

fish shell

macOS

Homebrew:

brew install fish

権限がない、もしくはシステムに痕跡を残したくない方は単独のアプリ(Automatorを使用しラッパー(Wrapper))をダウンロードし起動することができます。

Linux

Homebrewを導入していれば上記macOSのコマンドでも導入できます。

ディストリビューションが多くて、代表的なものですと:

sudo apt-add-repository ppa:fish-shell/release-3
sudo apt update
sudo apt install fish
dnf install fish

Unix

pkg install fish
pkg_add fish

Windows

MSYS2を導入している方は:

pacman -S fish

Fishをデフォルトシェルとして設定

インストールが成功したら、Fishをデフォルトシェルに設定することがおすすめです。多くのシステムではFishは同梱されていないことが多いので、システムにFishコマンドの場所を教えてあげる必要があります。

システムレベルで現在のログインしているユーザーのシェルをFishにするのにやることは二つ。

  1. /etc/shellsというデフォルトシェル一覧ファイルにFishコマンドの場所を追加
sudo sh -c 'echo $(which fish) >> /etc/shells'
  1. 現ユーザーのデフォルトシェルを設定
chsh -s "$(which fish)"

上記はUNIX系の環境であれば動くはずですが、つまづいたらググるもしくはチャチャる(ChatGPT)で調べてみてください。

Fishで出来ること

基本的に他のシェルで出来ることはFishで、もっと優雅にできます。

シェルスクリプトをプログラミングすることもできますし、シェルのプロンプトをカスタマイズすることができます。

Fish言語

シェルスクリプトのようにFishでプログラミングするためのFish言語が存在します。

細かくみたい方はこちらをご参考ください。

The fish language — fish-shell 3.6.1 documentation

この記事では代表的なところをご紹介します。

変数

全ての変数は配列です。Fishではリストとも呼びます。Bashと同じく配列メンバーをスペースで分けますが、ダブルコーテーションもしくはバックスラッシュでスペースをエスケープすることができます。

set var "foo bar" banana
set var foo\ bar banana # バックスラッシュでも同じ結果
printf %s\n $var

結果:

foo bar
banana

変数の代入時にコマンド結果を使用してもいいし、実値とコマンドを混ぜることができます。

set numbers 1 2 3 (seq 5 8) 9
printf '%s\n' $numbers

結果:

1
2
3
5
6
7
8
9

配列の一部を表示:

echo $numbers[5..7]

結果

6 7 8

関数

Fishの関数はコマンドのように使用ができ、補完するときの説明も追加することができます。

function hoge --description "関数の説明はこちら"
    echo $argv
end

Fishでの関数補完時に説明も表示されます
Fishでの関数補完時に説明も表示されます

Fishでの関数補完時に説明も表示されます

$argvは他のPOSIXシェルで使われる位置パラメータ($1,$2, …)の代わりであり、上記のように配列になっています。

ユニバーサル変数

これは他のシェルに見当たらないすごい機能であり、ユーザが起動中の全てのFishシェルに対して横断的且つ永久に変数値を設定することができるすごい機能です。つまりシェルの設定ファイルなどを手動で編集することなく、マシンを再起動しても残る変数です。

# このコマンドは、全てのfishシェルに対してプロンプトを青色に設定するものです。
set -U fish_color_cwd blue

上記のコマンドで設定された変数は~/.config/fish/fish_variablesに書き出されることがこの挙動の秘密のようです。

FishではPATH変数がユニバーサル変数として定義されています。

注意事項

Fishはユーザー体験や使いやすさに力を入れたシェル環境です。そのため、ZshみたいにBashPOSIXの互換性を維持するというミッションはないので、基本的に多くのBashの書き方は使用できません。バックティック```でコマンド実行することや、シェルの展開・置換(Bash expansion)は使えません。その理由はこういったシェル実装にバグやクセが多いからだそうです。その代変えとなるものはドキュメンテーションに書いてあります。

Bashシンタックスに慣れた方はドキュメンテーションの「BashユーザーのためのFish」(英語)をご参考願います。

Fish for bash users — fish-shell 3.6.1 documentation

Bashの書き方として使えて、Fishで使えない書き方の例(Wikipedia#Bash/fish_translation_table)より)

機能名 Bash Fish 備考
Fishでは中括弧は使えません ${var} $var Fishでは中括弧は使えません
配列の拡張 "${var[@]}" $var Fishの変数は配列なので、そのまま拡張されます。中括弧は使えません。
明示的なサブシェル (expression) fish -c expression サブシェルの呼び出し
プロセス置換 <(expression) (expression | psub) プロセス置換
変数代入 var=value set var value 単純にイコールサインの代入はできません。全てをsetコマンドで通す必要があります。
文字列処理(プレフィックスサフィックス、貪欲パターン、貪欲でないパターン) var=a.b.c
"${var#*.}" #b.c
"${var##*.}" #c
"${var%.*}" #a.b
"${var%%.*}" #a
string replace --regex '.*?\.(.*)' '$1' a.b.c #b.c
string replace --regex '.*\.(.*)' '$1' a.b.c #c
string replace --regex '(.*)\..*' '$1' a.b.c #a.b
string replace --regex '(.*?)\..*' '$1' a.b.c #a
stringコマンドを使用する必要があります。
文字列置換 "${HOME/alice/bob}" string replace alice bob $HOME stringコマンドを使用する必要があります。
変数のエクスポート export var set --export var setコマンドで通す必要があります。
関数のローカル変数 local var デフォルト仕様 関数の変数はデフォルトでローカルです
引数ベクター操作:シフト shift set --erase argv[1]
計算 $((10/3)) math '10/3' expr 10/3は外部コマンドなので、両方のシェルに使用できます
エスケープシーケンス $'\e' \e
環境変数を設定しながら実行 LANG=C.UTF-8 python3 env LANG=C.UTF-8 python3 env LANG=C.UTF-8 python3は外部コマンドなので、両方のシェルに使用できます

まとめ

Fishは大変使いやすいシェルでおすすめです。使いやすいし、Tabキー補完や履歴呼び戻しが直感的です。ぜひ使ってみてください。

株式会社フォトラクションでは一緒に働く仲間を募集しています

【Laravel】bootTraitsメソッドを使用して任意のテーブルのデータ保存をフックに共通処理を行う

こんにちは。CREの豊田(とよひろ)です。

以前LaravelのbootTraitsという便利なメソッドを発見したので記事にしたいと思います。

TL;DR


例えば、slackに通知したいとかアラートを出したいといった時に使えそうな便利な実装方法!

Itemテーブルなど、テーブル保存時に、ログを入れたいなどといったシーンで共通処理をいちいちコントローラー側に書いていくのはかなり大変ですよね。

Traitで共通処理を記載し、LaravelのModel.phpのbootTraits()メソッドをうまく使うと実現できます。

bootTraitsメソッドとは?


自身に使われているtraitの一覧を取得します。

つまり、使用しているクラス内のTraitの中にある「boot + Traitのクラス名」メソッドに対して、処理を行うことができます。

LaravelからEloquentクラスを調査してみる


保存をフックにするので

src/Illuminate/Database/Eloquent/Model.php

この辺を見てみる。

そうすると...

    /**
     * Boot all of the bootable traits on the model.
     *
     * @return void
     */
    protected static function bootTraits()
    {
        $class = static::class;

        foreach (class_uses_recursive($class) as $trait) {
            if (method_exists($class, $method = 'boot'.class_basename($trait))) {
                forward_static_call([$class, $method]);
            }
        }
    }

boot + Traitのクラス名で書くと勝手に呼び出してくれるようです。

なので、これを元にTraitを作れば解決しそうです。

以下実装例


trait Hogefuga
{
    /**
     * 保存時に共通処理をする
     *
     * @return void
     */
    protected static function bootHogefuga()
    {
        static::created(function ($model) {
            // 作成する時の共通処理
        });
    }
}

あとは、共通処理を挟み込みたいmodelクラスにuseしてあげればOK

User.php

class User extends Eloquent
{
    use Hogefuga;
}

Item.php

class Item extends Eloquent
{
    use Hogefuga;
}

作成時以外も対応してみる


trait Hogefuga
{
    /**
     * 共通処理をする
     *
     * @return void
     */
    protected static function bootHogefuga()
    {
        static::created(function ($model) {
            // 共通処理
        });

        static::saved(function ($model) {
            // 共通処理
        });

        static::updated(function ($model) {
            // 共通処理
        });

        static::deleted(function ($model) {
            // 共通処理
        });
    }
}

このようにしてあげることで本来、各コントローラーに記載しないといけないものがbootTraitsによってログを取れるようになります!

ぜひ試してみてください!

終わりに


リファレンスに記載されていないライブラリでも結構面白い、または便利なものがあったりします!!

github散歩等で触れたことのないライブラリを見つけてみるのも面白いかもしれません!😊

株式会社フォトラクションでは一緒に働く仲間を募集しています

AWS Chatbotで予算アラートするSlack通知をTerraformで実装する

はじめに

株式会社フォトラクションのSREをしている河野です。 フォトラクションのSREグループではAWS管理を任されているので、コスト監視を導入してみました。

やりたいこと

AWSの利用料金のしきい値を超えたらSlackに通知する。

やること

  1. AWSのマネコンでChatbotを開きSlackにアクセス権限をリクエストして承認する(この記事では省略します。マネコンからChatbotのページを開けばわかると思います)
  2. terraform apply
  3. SlackからAWSリソースを参照してみる
  4. 利用料金が超えるまで待つ

terraformのawsccというproviderを使用します。 terraformの内容と手順はこちらの記事を参考に、弊社の状況に合わせて修正を加えています。 AWS Budget notifications with AWS Chatbot, Slack and Terraform

Terraform

provider.tf

providerはawsに加えてAWS Cloud Control APIを使用するためのproviderであるawsccも追加します。chatbotのリソースはこちらのproviderを使用して作成します。

provider "aws" {
  region = var.region
}

provider "awscc" {
  region = var.region
}

resources.tf

locals {
  account_alias = data.aws_iam_account_alias.current.account_alias
}

resource "aws_sns_topic" "aws_budget_alerts" {
  name = "${local.account_alias}-aws-budget-alerts"
}

resource "aws_sns_topic_policy" "default" {
  arn    = aws_sns_topic.aws_budget_alerts.arn
  policy = data.aws_iam_policy_document.sns_topic_policy.json
}

# AWS Budgetsで予算とSNSへの通知設定
resource "aws_budgets_budget" "monthly" {
  name         = "budget-monthly"
  budget_type  = "COST"
  limit_amount = var.limit_amount
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator       = "GREATER_THAN"
    threshold                 = var.threshold
    threshold_type            = "PERCENTAGE"
    notification_type         = "ACTUAL"
    subscriber_sns_topic_arns = [aws_sns_topic.aws_budget_alerts.arn]
  }
}

resource "aws_iam_policy" "chatbot_role_policy" {
  name   = "chatbot-policy"
  policy = data.aws_iam_policy_document.chatbot_policy.json
}

resource "aws_iam_role" "chatbot_role" {
  name               = "chatbot-role"
  assume_role_policy = data.aws_iam_policy_document.chatbot_assume_role.json
}

resource "aws_iam_role_policy_attachment" "chatbot_policy_attach" {
  role       = aws_iam_role.chatbot_role.name
  policy_arn = aws_iam_policy.chatbot_role_policy.arn
}

resource "aws_iam_role_policy_attachment" "chatbot_policy_attach_read_only" {
  role       = aws_iam_role.chatbot_role.name
  policy_arn = data.aws_iam_policy.read_only_access.arn
}

# chatbotとSlackの連携の設定とSNSのサブスクライブ設定
resource "awscc_chatbot_slack_channel_configuration" "aws_budget_alerts_slack" {
  configuration_name = "slack_aws_budget_alerts"
  iam_role_arn       = aws_iam_role.chatbot_role.arn
  slack_channel_id   = var.slack_channel_id
  slack_workspace_id = var.slack_workspace_id
  sns_topic_arns     = [aws_sns_topic.aws_budget_alerts.arn]
  logging_level      = "ERROR"
}

awscc_chatbot_slack_channel_configurationでいろいろしてますので、やっぱり公式を参照するといいと思います。 awscc_chatbot_slack_channel_configuration

こちらのterraformでは、chatbot-roleに対して後述するdata.tfで取得したReadOnlyAccessのポリシーを付与しています。 slackからChatOpsするために権限を広く付与しているため、実際には適切な権限を付与するようにご注意ください。 (参考)SlackとAWS ChatbotでChatOpsをやってみよう

data.tf

data "aws_iam_account_alias" "current" {}

data "aws_iam_policy" "read_only_access" {
  name = "ReadOnlyAccess"
}

data "aws_iam_policy_document" "chatbot_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["chatbot.amazonaws.com"]
    }
  }
}

data "aws_iam_policy_document" "chatbot_policy" {
  statement {
    actions = [
      "sns:Subscribe"
    ]
    resources = [
      "*"
    ]
  }
}

data "aws_iam_policy_document" "sns_topic_policy" {
  statement {
    actions = [
      "sns:Publish"
    ]

    principals {
      type        = "Service"
      identifiers = ["budgets.amazonaws.com"]
    }

    resources = [
      aws_sns_topic.aws_budget_alerts.arn
    ]

  }
}

複数のAWSアカウントからの通知を想定してアカウントのエイリアスを取得しています。

variables.tf

variable "region" {
  type = string
}

variable "slack_channel_id" {
  type = string
}

variable "slack_workspace_id" {
  type = string
}

variable "threshold" {
  description = "予算に対して何%で通知するか"
  type        = number
}

variable "limit_amount" {
  description = "利用料金($)の予算、なぜかstringらしい"
  type = string
}

SlackからAWSリソースを参照してみる

awsをChannelに追加してから@awsawsに話しかけるとコマンドが実行できます。

# 例
@aws sns list-topics

取れました。ARNにAWSが主張しているのはご愛嬌。(:aws:でEmojiが登録されているためです)

予算アラート通知

少ない予算ですぐに通知が来るようにして通知結果を確認しました。

結局アカウントIDしかAWSアカウントを特定するものがなかったので、Budget nameあたりにアカウント特定のエイリアスを入れると良さそうです。

まとめ

terraformで予算アラートを設定してみました。マネコンからの操作があるのはどうしようもなかったですが、割と簡単に予算通知を入れることができました。 AWSアカウントが増えすぎると結局管理が大変になるのでAWS Organizationsなどのサービスも検討していこうと思います。

株式会社フォトラクションでは一緒に働く仲間を募集しています

目標設定の改善をおこなってみる

CREチームリーダー田中です。突然ですが、目標設定って難しいですよね。

一メンバーとしてもそうですが、リーダーとして、メンバーの目標設定をフォローする立場になり、より難しいな〜と感じています。

今回、記事を書くにあたり、より良い目標設定や、フォローアップができるよう、勉強して、改善に繋げてみようと思います!

目次

実際にCREチーム内で立てたやり方

実際立てていたのは以下のような目標です。

  • 調査タスク○件
  • 調査対応○件(PR数)

前提として、

目標設定は、評価制度に紐づいています。

CREチームメンバーは、未経験エンジニアを採用し構成されています。

不具合の調査や改修チケットをこなしていくことで、スキルアップしてもらい、開発チームに巣立って行ってもらうことを目標に置いています。

なので、ある程度数をこなして成長してもらえるような指標を置いています。

尚且つ、評価者、被評価者が評価しやすい(されやすい)且つ、評価に納得しやすくなるよう、できる限り定量的な値を置くことを意識しました。

なぜ、目標設定するんだっけ?

目標設定の概要は、Wikipediaではこうなっているらしい。

目標設定には、個人またはグループを動機づけ、目標に向かって導くために設計された行動計画の作成が含まれます。目標は、願望や瞬間的な意図よりも計画的なものです。したがって、目標を設定するということは、人が目標を達成するために思考、感情、行動をコミットさせることを意味します。

つまるところ、目標設定とは、以下に言い換えられます。

  • 目標を達成するために立てるもの
  • 突発的な願望ではなく、プランニングが必要
  • 「目標を達成するぞ!」と気持ちを固めること(=コミットする)

1点目、2点目は、まぁそうだよなと思いましたが、3点目は個人的には意外でした。

字面の通り、「目標」を「設定」するというアクションの意味だけではなく、

そのアクションに「達成するぞ!」という感情が乗ってくるのが非常に面白いなと。

上記は英語のWikiを和訳したので、英語圏の方々の目標設定の価値観なのかもしれないですね。

当たり前ではありますが、達成するために、目標を立てる精神は大事!

目標設定のフレームワークを見てみる

次に、目標設定の文脈でよく使われるフレームワークを紹介します。

フレームワーク

  • MBO
    • 目標管理制度(MBO:Management By Objectives)
    • ピーター・ドラッカーが提唱したプログラムで、担当者が主体的に業務目標を設定し、その進捗を自ら管理する手法
    • メンバーが自分で目標を決めるため、主体性を伸ばし、パフォーマンスやモチベーションを高めたり、人材育成、人事評価の効率化したりと、様々な効果が期待できる
    • 人事評価に紐づいた、個人目標
  • OKR
    • 目標と成果指標(Objectives and Key Result)
    • MBOから派生した、目標管理の一種
      • MBOとの共通点
        • 組織と個人の目標を共通化すること
      • MBOとの差別点
        • 組織の評価制度と紐付けない
        • 難易度の高い目標に挑戦させることにより、飛躍的なパフォーマンス向上を狙う
    • 人事評価に紐づかない、個人目標
  • KPI
    • 重要業績評価指標(Key Performance Indicator)
    • KGI (Key Performance Indicator。重要目標達成指標)を達成するにあたって、その過程で、どれくらいの状態をクリアしていればいいのかを可視化して、計測するための指標
    • 個人目標ではなく、あくまで業務目標

参考:https://www.staffservice.co.jp/client/contents/management/column031.html

SMARTの法則

また、「目標設定 やり方」とかで検索するとSMARTの法則というワードが上位に出てきます。目標設定の定め方としてよく使われる考え方で、以下の頭文字の単語を総称しています。

  • Specific(具体的に)
  • Measurable(測定可能な)
  • Achievable(達成可能な)
  • Relevant(経営目標に関連した)
  • Time-bound(時間制約がある)

こちらは、Relevant(経営目標に関連した)とあるので、人事評価に紐づいた、個人目標の文脈のようですね。MBOの目標設定の方針と合致するので、こちらを基に改善してみようと思います!

参考:https://globis.jp/article/659

改善に繋げよう

今回立てた目標と改善点

実際立てていたのは以下のような目標です。

  • 調査タスク○件
  • 調査対応○件(PR数)
  • Specific(具体的に)

    →チケット単位なので、何にコミットするか具体的である

  • Measurable(測定可能な)

    →チケットの件数は定量的である

  • Achievable(達成可能な)

    →ストレッチ目標で立てていますが、達成不可ではない(と思っています)

    • ただメンバー本人が達成できると信じられているかは不明(擦り合わせられていないかも)
  • Relevant(経営目標に関連した)

    →CREチームの業務内容に合致。スキルアップをチーム目標に置いているのでそちらにも合致します

    - こちらも、明示して、目線合わせできてるわけではない

  • Time-bound(時間制約がある)

    →半期内の区切りはしているが、中間目標としては置けていなかったので、改善!

改善後イメージ

  • Achievable(達成可能な)
  • Relevant(経営目標に関連した)

の目線合わせを行った上で、例えば、

○/○~△/△までに、調査対応○件(PR数)対応する!

みたいな文言で目標を定めようと思います。

今回定めた目標設定をフォローする

上記は、来期の目標設定の時に活かすとして、

今回不十分だった点は、コミュニケーションでカバーしようと思います。

具体的には、以下の2点。

  • Achievable(達成できる)
  • Time-bound(期限が明確な)

隔週で1on1を実施しているので、その際にこの観点を確認し、意識づけてもらおうと思います!

まとめ

意外と体系的に学ぶことのない、目標設定。

もちろん、目標達成することが第一ですが、達成できた/できないに囚われすぎるのはそれはそれでよくないなと思っています。

その過程で、どれだけできることが増えたかなど、成長率にも重きを置いていくことを忘れず、目標達成のフォローをしていこうと思います!

株式会社フォトラクションでは一緒に働く仲間を募集しています