Photoruction工事中!

Photoructionの開発ブログです!

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を実施しているので、その際にこの観点を確認し、意識づけてもらおうと思います!

まとめ

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

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

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

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

目標設定と1on1での成果確認の重要性を実感

QAチームリーダー塩谷です。

今年は目標設定の重要性と1オン1での成果確認の重要性を改めて感じる機会がありましたので、振り返りを含めて記事にしたいと思います。

目標設定について

皆さんは自己成長のために、自身の上司とスキルアップや業務における成果目標などの設定を行い、その内容を共有しているでしょうか?

時間は否が応でも流れていき、時代は移り変わっていきます。

会社は時代に合わせて成長していかなければ廃れてしまい、会社を成長させていくためには社員それぞれが成長していかなければなりません。

そして成長に欠かせないのが目標設定とその成果確認になります。

設定した目標を上司と(会社と)コミットし、その成果を確認することで、各自の成長度合いを把握することができ、会社は適切に各自の評価をすることが出来ます。

また管理側では、各自の目標を管理することでその人がどういう方向性に進んでいきたいのか、目標に対して順調に進んでいるか・問題は発生していないか、モチベーションを維持できているかなどの把握がしやすくなります。

1オン1について

多くの会社で1オン1を実施していると思います。

1オン1では、メンバーの成長を促す目的や何か問題を抱えている・会社に対して不満が溜まっているのを取り除き従業員満足度を高める目的などがあります。

普段コミュニケーションを取っている関係でも改めて時間を確保することで

雑談などでは話せない問題を話したり、1オン1だからこそ意味のある会話が生まれたりします。

私はメンバーと月に一度1オン1を設定しており、その中でメンバーの目標設定に対する進捗を確認しています。

目標設定に対する進捗を確認することで、ちゃんとアクションできているか・問題が発生していないかを確認でき、問題がある場合には1オン1の中でメンバーと対話して解決していきます。

またアクションを起こした結果、元々の目標設定が良くなかった場合は、目標自体を変更していくこともあります。

目標設定の大切さ

今年はある事情によって目標設定をしなかったケースがありました。

結論から申し上げると該当のメンバーは退職という形になりました。

退職の理由は様々ありますが、振り返ってみると会社からの期待値と本人の方向性と現状が一致していなかったことが原因の1つにあったと思います。

1オン1を実施する時に「何か問題はない?」という曖昧な質問をしてしまい、

問題を的確に捉えることが出来ずに、1オン1を重ねることで根本的な問題があると考え、

しっかりと目標設定を行なって、1つずつステップアップしていこうとしていた矢先に退職という結果になりました。

もっと早く目標設定を一緒に実施していれば、本人の将来の意向と現在地を精度を高めて把握できたと思います。

さいごに

目標設定や1オン1は多くの会社で取り入れていると思いますが、形式的に実施しているだけになっていないでしょうか。

特に管理者は優秀な人材を流出させてしまわないように、1オン1などで小さな問題をしっかりとキャッチアップできるように心がける必要があります。

会社として実施している様々なイベントは、決して形式的なものと考えずにそれぞれが意義のあるものとして捉え、取り組んでいきたいと思います。

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

1on1から得た学び

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

今回のテーマは定期的に行われるけどルーティン化されがちな1on1について、自分のアクションや意識をどう変えたかについて執筆しました!

自分の経験が、誰かの役に立つかはわかりませんが、きっかけ作りの一端を担えればと思いますので、興味がある方はぜひご一読お願いします🙇‍♀️

以前の記事はこちら↓↓↓

kojichu.photoruction.com

1on1について今までどのように考えていたか


皆さんは1on1を上司とするにあたり、どんなことを意識してますか?

僕は、今まで1on1を以下のような場だと思い、望んできました。

  • 分かんないこと/困っていることを相談する場

普段のデイリーは、全体会議のため時間の都合上細かすぎる内容については聞くことができないため、1on1という場で詳細なことを聞くことで情報の補完を行うものだと思っていました。

また、自分がその際困ったことなどを共有することで、上長はそれに対して何かしらのアドバイスをくれるという認識で、受け身の姿勢であったと思います。

これは1on1に限った話ではなく通常の会議にも言えることですが、ファシリがいるとどうしてもその人任せで主導してもらうことが多くなり、受け身でいる事が多い気がします…(もしかすると、日本人特有のものかも?)

招待された参加者気分であったのが今までの僕です。

1on1を意識するようになったきっかけ


1on1を4~5回こなしたくらいから、ふと振り返ったときあることに気づきました。それは相手に題材を用意してもらってそれをもとに、質問をされることで回答をしていくという一方通行のコミュニケーションがなされているという事。つまり、受け身の姿勢であるという事実をここで初めて理解しました。

きっかけは些細な事で、過去の1on1の内容をまとめた議事録を読み返したから得られた気づきでした。内容を見ていると、質問された内容についてただ回答しているだけで、学校の授業となんら変わらない受動的なスタイルが1on1では起きていました。

このままの状態では、自己成長できるはずがないと思い、改めて1on1について考える事にしました。

そもそも1on1って


自分にとっての1on1とは何かを考えた時、「成長機会を得る場であると同時に自分にない視野・視点・視座からの気づきを得る場」であると思いました。

上長だからこそ見える視点、自分だからこそ見える視点、それぞれの視点を共有する事で、自分にはない視点に気づく事ができる。その視点を得ることで、別のアプローチを試せるようになったり、問題解決への糸口を掴む事ができるのかなと思います。

また、成長機会を得る場であるという意識は結果として、自発性を促進する効果もあると考え、これらの気づきを得る事が自分にとっての1on1の定義かなと思いました。

これらを念頭に、具体的に1on1をする際にどんなことを意識するようになったのかについてお話ししていきます。

1on1で意識するようになったこと


1on1の意義を再確認し、以下のようなアクションを試すようになりました。

1.自分が気付かない視点からのアドバイスをもらう

自分からの視点だと、物事の一部しか見る事ができず、その部分以外を見る事ができません。

そのため、1on1では2週間の振り返りとして以下のような形でフィードバックを取りに行くようにしています。

下記は実際に使っているテンプレートです。

💡 <先週の振り返り>

- 先週、先々週で、行動で何かまずいところや要改善ポイントはあった(見つかった)か

[自分視点]

- 〇〇について、〇〇のようなアクションをとれば、工数を削減できた。

[リーダー視点]

- 〇〇のタスクについては、こういうアクションをとることもできたのではないか。

2.成長機会の場という意識

認識を改めたことで、1on1は自己の成長機会の場であると考えられるようになりました。事前にアジェンダをまとめて情報を提供することで、今の自分に必要なアドバイスを得る事ができ、30分という短い時間でも濃密な時間を過ごす事ができています。また、それを元に質問を受ける事で、自分の思考の癖なども知る事ができ、自分を知る機会にもなっていたりします。

3.「1on1という場」を一緒に作っていく意識

2と関連してるのですが、自己の成長の場であるという意識を持つことは受身の姿勢がなくなり、自然と前のめりになるため、「1on1という場をどういう場にしたいか?」を考えるようになりました。会議などでもそうですが、自発性がないとどうしても聞き手に回りがちだと思うので、「成長機会を得る」という意識は副作用として、色々な面で役に立つなと改めて思いました。

意識したことで、どのような効果があったか


効果としては、主に2つあります。

  • 自分の行動を省みるきっかけを作ることができた
  • 他の人の経験や知識から、自分の視野を広げる事ができた

自分の行動を省みるきっかけを作ることができた

業務をこなしていると自分の行動を省みるタイミングって中々作りづらかったのですが、1on1のタイミングで、その機会を作る事ができたので、結果として業務中でも「これは1on1で相談したい案件だな〜」みたいな成長機会を得るための意識が以前よりも働くようになりました。

他の人の経験や知識から、自分の視野を広げる事ができ、複数の視点も持てるようになった

他の人の視点から得た学びを自分の視点に活かす事ができ、結果として視野を広げて物事を判断できるようになっていると思います。例えば、今までは自分の視点頼りの発想も別のアプローチを試みることもできるようになり、幅が広がった気がします。

1on1を通して感じた大事なこと


これは個人の主観になりますが、やはり自発性が大事だなと思いました。ただ、今回のようにそもそも自分が受け身であるということに気づけないと、自発的に何かをやるといった行為は難しいと思うので、自発性と同じくらい自分の行動を省みる事が大事であるなとも思いました。

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

Vimの繰り返し操作まとめ

こんにちは。CREの田島です。

少し前からAI活用エディターのCursorが話題ですよね。

ただし、本記事は生まれたてエディターCursorについてではなく、リリース32周年を迎えたVimについての記事になっていますので注意です。

「AIを活用した」なんて甘美な響きではありませんが、Vimにも魅力的な個性が多いですよね。

キーバインドがその代表かと思いますが、「繰り返し操作のやりやすさ」もそのひとつかなと思ったので、Vimの繰り返し操作についてまとめました。

直前の変更を繰り返す

.(ドット)を使います。

例えば、ddで一行削除した後に、.を押すと一行削除が繰り返されます。

直前のExコマンドを繰り返す

@:を使います。

例えば、:vsでウィンドウを分割した後に、@:とするとさらにウィンドウを分割します。(この場合、:vsをもう一度入力する方が楽かもですが、例として)

履歴からExコマンドを繰り返す

q:を使います。

Exコマンドの履歴と一緒にコマンドラインウィンドウを表示します。

履歴を編集してExコマンドを実行することも可能です。

履歴から検索を繰り返す

q/,q?を使います。

検索履歴と一緒にコマンドラインウィンドウを表示します。

履歴を編集して検索をすることも可能です。

(検索には正規表現を使用できますが、クセがあります)

直前の置換を繰り返す

:&&を使います。(:&&の場合、現在行のみに作用します。)

以下のテキストを編集するとします。

Photoructionは建設業の生産性向上を目的としたクラウドサービスです。
テクノロジーとオペレーションの力で10倍を超える業務効率化を実現します。
大手ゼネコンをはじめ、100,000を超える建設プロジェクトで導入されている国内最大規模のサービスです。

私たちが考えるのは常に建設業で働く皆様のことです。
主力サービスである建設生産支援クラウドPhotoructionは、
リリースして3年半ほどで100,000を超える建設プロジェクトで使われるようになりました。

3行目の100,000を200,000へ置換した後、7行目も同様に置換したい場合は、:&&とすればOKです。

↓入力キーの例

3G
V:s/100,000/200,000/g
7G
:&&

ひとまとまりの操作を繰り返す

1~10の連番生成を例にします。

レジスタaに記録し、それを繰り返します。

↓入力キーの例

i1<Esc>
qa
yyp<C-a>
q
8@a

(単純な連番生成ならマクロ使わない方が楽です)

↓入力キーの例

yy9P
VG
g<C-a>

直前に実行したマクロを繰り返す

@@を使います。

直前に記録したマクロを実行したい場合は、Qです。

まとめ

これらの繰り返し操作がコーディングの中で使われることは稀だと思います。

ただ、エディターとしてではなく、テキスト整形ツールとして見たとき、これらの操作が輝ける瞬間があるかもしれません。

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