TECH PLAY

ニフティ株式会社

ニフティ株式会社 の技術ブログ

500

はじめに こんにちは。新卒4年目の大里です。 7/11に行われたレバレジーズ x ココナラ x ニフティ 合同フロントエンド勉強会に参加しましたので感想を書きます。外部の勉強会に初めての参加と発表だったため、勉強会に参加したことがない方、発表したことがない方の参考になれば幸いです。 レバレジーズ x ココナラ x ニフティ 合同フロントエンド勉強会とは この勉強会は名前の通りレバレジーズ株式会社様、株式会社ココナラ様、ニフティ株式会社の社員がフロントエンド開発について自由なテーマでLTをするオンラインの勉強会でした。詳細は connpass を参照してください。 なぜ勉強会に参加&発表しようと思ったか 社外のエンジニアの勉強会の雰囲気をつかみたかった 独学で本を読むなどをしてデザインを少し勉強してきたのですが、独学以外の勉強方法として社外の勉強会に参加することの効果や意義を知りたくて参加しました。同僚から社外の勉強会に参加した話を聞いてみて面白そうと思ったのですが、どの点がどう面白そうかが自分で腑に落ちておらず実際に体験してみて違いを感じ取ろうと思いました。 この勉強会に参加したのは、他の勉強会よりも気楽に参加できるように感じたためです。企画者が社内の勉強会と同じように気楽に発表ができる雰囲気になるよう工夫してくださりました。おかげさまで気分転換初めて社外勉強会に参加や発表するときにハードルが高くないように感じ、この勉強会に参加しました。 通常業務とは別の業務を並行で実行したかった 当時、事業案件や運用などの通常業務がうまくいかないことが多くモチベーションが下がっておりましたが、通常業務とは別の業務をしてみることでモチベーションが上がる可能性があると仮説を立てました。通常業務のみを遂行していた場合、通常業務がうまくいかなかった時にマイナスの気持ちになることが多く、このままの状態が続くとモチベーションの低下になりうると考えました。しかし、別の業務も行った場合にプラスのことが起きていればモチベーションが安定する可能性があると思いました。この仮説が成立するのであれば、今後の業務でモチベーションを保てるように、通常業務とは別の業務を遂行することを意識していきたいという意図がありました。 参加した感想 良かったこと 他企業の実際の業務で、どのように技術を使っているかを知ることができた 独学と社外の勉強会の違いを大きく感じられた点でした。担当業務ではバックエンドの業務が中心で、少しフロントエンド側でデザインの修正をする程度でした。勉強会ではフロントエンドのパフォーマンスの改善など、業務で触れたことのない分野で他社がどれだけ工夫をしてきたかを知ることができました。デザインのみを独学していた時よりも、フロントエンドに対する視野が広がったように思います。 事業案件や運用などの通常業務とは別軸の業務をして気分転換になった 勉強会の準備の際は自分の責任で自分の好きなように発表内容を考えられることや締め切りに追われているときなど、学生の時の文化祭の前準備や研究のデモの準備に近い状況があったため楽しかったです。通常業務の中でプレゼンテーションをする機会はあまりないため、普段はあまり使わないけれど社会人として必要なスキルについて考えるきっかけになりました。通常業務をする上であまり意識できていなかったため、新鮮な気持ちになりました。 社外勉強会の雰囲気が分かって安心した 勉強会の準備をする時間はどういった発表をすればよいか分からず不安な気持ちもありました。しかし、勉強会で発表したり他の人の発表を聞いてみたりすることで社外の勉強会の雰囲気が少し分かった気がします。そのため勉強会の雰囲気を知らなかった今回の発表準備の不安よりは、今後の発表を準備するときの不安は軽くなると思いました。 他企業のエンジニアの話すことが想定したよりも楽しかった 就活時代に様々な企業で働いている方とお話しましたが、自分が働きだしてから他の企業の方とお話をすると解像度が高くなることを実感できました。フロントエンドの勉強会でしたが、各企業のプロジェクトの進め方や使用する言語の選定方法など、各企業の業務の進め方をお伺いすることができて楽しかったです。社内で働いていて知ることができなかった他企業の働き方を知ることができたため、自分のキャリアを見つめ直すきっかけにもなりました。 反省点 勉強会の準備を計画的にできず体力的にきつかった 理想は業務時間内に勉強会の準備の時間を取って通常業務と進められることでしたが、計画性がなく残業時間を使って勉強会の準備をしてしまいました。残業して勉強会の準備をするのは体力的に厳しかったため、通常業務とのバランスのとり方が今後重要になってくると思いました。 まとめ 初めて社外の勉強会に参加してみましたが、他社の業務や開発で気を付けていることを知れたことが新卒からニフティに入ってきた身として、とても新鮮でした。想定していた社外勉強会のメリットより多くのメリットがあることが実感できてよかったです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは。会員システムグループの渡邊です。 Google Analyticsのユニバーサル アナリティクス(UA)が2023年7月1日をもってサポート終了した影響で、Googleアナリティクス4(GA4)への移行とUAと連携していたBIツールの変更が必要になりました。 移行後のBIツールとして採用したLooker StudioとGA4の連携方法と、期間別にユニークユーザー(UU)を出しているときに発生したハマりポイントをまとめました。 やりたいこと GA4に蓄積しているUU数を期間別(月、週、日)に分けてグラフで見れるようにしたい 準備 Looker Studioでレポートを作成する データに接続でGoogle アナリティクスを選択 Googleアカウントに連携されているGAのアカウントが表示されるので、期間別に分けたい情報を持っているアカウントを選択する これで準備完了です。 グラフで見れるようにする 月別 グラフを追加 を押し、縦棒グラフを選択する 作成したグラフを選択し、設定を以下のように変更する 設定 ディメンション 月 指標 アクティブ ユーザー数 並び替え 月 デフォルトの日付範囲 カスタム(今年) 週別 ハマりポイント デフォルトの設定では集計対象の週の最大値を取るようになっているため、週単位の集計はGA4の値と合致しません。 実際には週の終わりの値を取るのが正しいので、週の集計期間を週の終わりである日曜日に指定するフィルターを追加することで対応しました。 下の画像のようにフィルターを設定しないと差が生じることがわかります。 設定 ディメンション ISO年のISO週 週 というディメンションでも同じ値になるが、1年における何周目という表示になるので分かりづらい 指標 7日間のアクティブ ユーザー数 並び替え ISO年のISO週 フィルター 一致条件→曜日→次に等しい→1 週の終わりである日曜日(1) 日別 設定 ディメンション 日付 指標 1日のアクティブ ユーザー 並び替え 日付 デフォルトの日付範囲 カスタム(今年) これで期間別のグラフは完成です。 まとめ GA4は具体的な集計方法が公開されていないので、GA4に表示されている値がどの項目を見ているかを探り当てるのに時間がかかりました。 GA4とLooker Studioを連携すると GA4で持っている細かいデータ を見ることができるので、分析の幅が広がりますが、多機能なので慣れるまでには時間がかかると思いました。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに インフラシステムグループ ISPオペレーションサブチームの藤川です。 ニフティが皆様の目に触れる際にISP(Internet Service Provider)と呼ばれる機会も減ってきて少し寂しいところもありますが、本業は回線提供であると主張します。 総務省のレポート “ https://www.soumu.go.jp/main_content/000861552.pdf ” でもあるとおり、インターネットのトラフィックは年々増え続け、それはインターネットで出来ることが年々広がってきた軌跡ですね。 私が所属するISPオペレーションの業務はそんなインターネット回線が日々快適に使えるよう関係各方面と調整を続ける仕事です。 高トラフィックイベントとは 回線運用で頭を悩ますのはリアル世界やインターネット界隈で発生するイベントがきっかけで発生する一時的な高トラフィックです。 たとえば台風・地震などの災害が発生したときの情報収集や安否確認、たとえばスポーツの世界大会やボクシングのタイトル戦など優秀な日本人選手が活躍する試合、たとえば参加者が多い覇権ゲームの大規模アップデート、たとえば皆さんがお使いのパソコンのOS定例アップデートなどにあたると一斉に通信をしますので全体の通信量は膨大な変化となります。 みなさまもインターネットを使っていて「今日は重いな」とか、「1秒でも早くダウンロード終わらせて新しいゲームを始めたいのになかなかDL出来ない」など、日によって回線が遅いことを感じたことは無いでしょうか?そういったことを私たちは高トラフィックイベントと呼んでいます。 これに備えるために国内では総務省の音頭でCONECTという協議会活動 “ https://www.soumu.go.jp/menu_seisaku/ictseisaku/conect/index.html ” があったり、弊社でもユーザーサポート・サービス企画・回線運用の各チームで情報のキャッチアップと事前の対策検討を進めています。 ゲームのアップデートを予測する 高トラフィックイベントの対応に忙殺させられる中で、ふと過去の履歴を振り返るとアップデートには規則性があるように感じました。 従来、定期的に高トラフィックが発生してしまう対象として有名なOSのアップデートは提供元が年間スケジュールを予告してくださるので助かっていますが、ゲームのアップデートは気づいたら提供が始まっていて当日になって慌てて対応する認識でした。 そういうことで、影響が大きいゲームをいくつかピックアップして日時を確認すると、だいたい3か月周期でメジャーアップデートと呼ばれる大容量ファイルのダウンロードがあり、その合間に繰り返しマイナーアップデートがありました。 詳細に見てみましょう、、、、 ゲーム1の場合 とあるゲームのバージョン番号を時系列にしたのが図です。すごく一直線ですね。時々ある段差も気になります。すべてのファイルサイズを記録できていればよかったのですが、直近数件のみです。全体の角度が一定と言うことは、メジャーアップデートは一定間隔で実施されていることになります。 グラフで確認するのは良くないようですので、諦めて表で確認します。 このように俯瞰すると3か月おきにメジャーアップデートがあり、その間はばらつきがあるものの、平均2週間おきにマイナーアップデートを提供しているようです。また、マイナーアップデートは火曜、メジャーアップデートは週末が多い様でした。 前後のファイルサイズから想像すると、ばらつきの原因はスケジュール遅延でしょうか。お疲れさまです。 こちらのゲームのマイナーアップデートはファイルサイズが小さい事が多く安心ですが、メジャーアップデートは数GBのサイズがあります。そのうえ、このゲームはお子様から大人まで幅広い年齢層に愛されていてトラフィックインパクトが大きいです。こういう時こそ快適に利用して頂きたいから非常に頑張りがいがあります。 ゲーム2の場合 また違うゲームを確認します。 とあるメジャータイトルのアップデート日時となりますが、年1回のメジャーアップデートに加え、マイナーアップデートが定期的にあります。日付はバラバラに見えますが、右欄を見ると6週間隔で水曜日にリリースしていることがわかります。 このゲームはファイルサイズが毎回10GB前後と大きいから大変です。 おわりに このように、世の中で大勢の方に愛されるOSやゲームは、ある程度各社のポリシーに従って提供されていることがわかってきました。 少し前にサスティナブルと言う言葉が流行っておりましたが、持続的にリリースをしてユーザーの期待を裏切らず、サービスを維持する実績には脱帽する限りです。きっとこのような開発を実行するためにアジャイル開発というものが重視されているのでしょう。 使う人のニーズが無ければ必要とされない通信インフラですのでアップデートで必要とされるのは本望ですが、提供側にはサイズ軽減を、ユーザーの方々には混雑していない時間帯にダウンロードして頂くと、中の私たちがちょっとだけ幸せになれます。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass カジュアル面談も受け付けています! ニフティ株式会社 – Meety
アバター
はじめに こんにちは。いかりがわです。 普段はニフティトップページの開発運用を行っています。 このプロダクトの裏側ではGoで記述されたLambda関数がいくつか動いています。 公式からLambda関数についてメールが届きました。どうやらLambda関数のGoランタイムサポートが2023/12/31にサポート終了するらしいです。 お客様の AWS アカウントに現在 Go 1.x ランタイムを使用する 1 つ以上の Lambda 関数があることを確認しましたので、ご連絡いたします。 Amazon Linux AMI のメンテナンスサポートが 2023 年 12 月 31 日に終了するのに合わせて、AWS Lambda での Go 1.x ランタイムのサポートを終了します [1]。 Lambda は、provided.al2 ランタイムを使用して Go プログラミング言語を引き続きサポートします。 provided.al2 ランタイムを使用すると、AWS Graviton2 プロセッサのサポートや、より小さなデプロイパッケージとより高速な関数呼び出しパスによる効率的な実装など、go1.x ランタイムに比べていくつかの利点があります。 詳細については、ブログ記事 [2] を参照してください。 Goのランタイムは Amazon Linux AMIに基づいています。Amazon Linux AMIのサポートが 2023/12/31に終了するに伴い、Goのランタイムもサポート終了となるようです。 Goのランタイムで動作しているLambda関数は、ランタイムを provided.al2 (Amazon Linux 2 AMIベースのカスタムランタイム)に移行する必要があります。 何故Amazon Linux 2 AMIでGoのランタイムをサポートしてくれなかったんだ。。。。 AWS公式からの見解としては以下です。 Go は、他のマネージドランタイムとは異なる方法で実装されています。Go はネイティブコードにコンパイルされるため、Lambda は Go をカスタムランタイムとして扱います。 provided.al2 ランタイムを使用して Go 関数を Lambda にデプロイすることをお勧めします。 Go による Lambda 関数の構築 – AWS Lambda つまり、「コンパイル後はネイティブコードになるんだからわざわざGoのランタイムとして用意する必要ないやろ」と言うことです。 なので今回は、サポート終了してしまう go1.x のランタイムから provided.al2 のカスタムランタイムに変更していく手順をまとめていきます。 前提 Lambda関数をTerraformで構築するためのディレクトリ構成は以下のようになっています。 . ├── lambda │ ├── archive // 圧縮後のファイルを保存するディレクトリ │ ├── build // バイナリを保存するディレクトリ │ └── cmd // goのワーキングディレクトリ │ ├── go.mod │ ├── go.sum │ └── main.go └── main.tf また、Lambda関数の中で動いているコードは以下のようになっています。 package main import ( "context" "fmt" "github.com/aws/aws-lambda-go/lambda" ) type MyEvent struct { Name string `json:"name"` } func HandleRequest(ctx context.Context, name MyEvent) (string, error) { return fmt.Sprintf("Hello %s!", name.Name), nil } func main() { lambda.Start(HandleRequest) } 変更してみる aws_lambda_functionのruntime ランタイムをgo1.xからprovided.al2に変更します。 前述の通り、コンパイル後はネイティブコードになるため、ランタイムはAmazon Linux 2 AMIベースのカスタムランタイムを指定します。 resource "aws_lambda_function" "lambda" { function_name = "go-lambda-sample" filename = "./lambda/archive/sample.zip" role = aws_iam_role.lambda_role.arn handler = "sample" - runtime = "go1.x" // 変更前 + runtime = "provided.al2" // 変更後 source_code_hash = data.archive_file.lambda.output_base64sha256 } ビルド後のファイル名 現状のビルド周りのコードは以下のようになっています。 おそらく、TerraformでGoのLambdaを構築する際の一般的な方法だと思います。 resource "null_resource" "default" { triggers = { always_run = timestamp() } provisioner "local-exec" { command = "cd ./lambda/cmd/ && GOOS=linux GOARCH=amd64 go build -o ../build/main main.go" } } data "archive_file" "lambda" { type = "zip" source_file = "./lambda/build/main" output_path = "./lambda/archive/sample.zip" depends_on = [null_resource.default] } 今回は、 go build の部分を変更します。また、変更後に圧縮するため、圧縮元ファイルも変更します。 カスタムランタイムでは、実行ファイル名は bootstrap である必要があります。なので、 go build は以下のようになります。 cd ./lambda/cmd/ && GOOS=linux GOARCH=amd64 go build -o ../build/main main.go ↓ cd ./lambda/cmd/ && GOOS=linux GOARCH=amd64 go build -o ../build/bootstrap main.go 圧縮元ファイルも bootstrap に変更します。 data "archive_file" "lambda" { type = "zip" source_file = "./lambda/build/bootstrap" output_path = "./lambda/archive/sample.zip" depends_on = [null_resource.default] } 確認 実際にコンソールから確認してみます! ランタイムがAmazon Linux 2 AMIベースのカスタムランタイムになっていることが確認できます! テストでお試し実行してみても問題なく動作することが確認できます! 意外と簡単にGoランタイムからAmazon Linux 2 AMIベースのカスタムランタイムに移行できることがわかりました。 急いで移行する必要はないですが、簡単に移行できるので早めに移行することをお勧めします! 注意:コールドスタートにかかる時間も請求に含まれる 冒頭のメールに以下のような内容が記述されています。 Lambda の請求には、go1.x ランタイムと provided.al2 ランタイムとの間に違いがあります。 go1.x ランタイムでは、Lambda は関数の初期化 (コールドスタート) に費やされた時間を請求しませんが、provided.al2 ランタイムでは、Lambda は請求される関数実行時間に関数の初期化時間を含めます。 Go 関数は通常非常に迅速に初期化され、Lambda は複数の関数呼び出しに関数実行環境を再利用することで初期化の回数を減らすため、実際には Lambda 請求額の違いはごくわずかです。 カスタムランタイムに変更すると、コールドスタートにかかる時間も請求に含まれるため多少請求額に変化があるかもしれません。 GitHub サンプルコードはこちらに公開しています。 https://github.com/k0825/go-lambda-al2-sample   We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も常時受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは、ニフティの佐々木です。 みなさんは、 Notion は好きですか?NotionではUIベースで様々なことを実現できるので便利ですよね。 個人的にも最近はドキュメントを書くだけでなく個人的なタスク管理としてもガッツリ使っているので、無くてはならない存在だなと感じます。 今回はNotionの機能の一つである NotionDB を用いて、スクラム開発で使用するSBIとPBIのカンバンボードを作りながら、あれやこれやの欲しい機能を無理やり自動管理で実現してしまおう!という記事になります。 この記事の内容 NotionDBを用いたカンバンボード自動化方法 ※ なお、この記事はNotionとスクラム開発の基本的な知識を既に持っている読者を対象にしています。 準備 前提条件 スクラムのカンバンボードで使用するSBI・PBIの管理といっても色々あるので、ここでは以下の条件で考えてみます。 スプリント期間(2週間など一定の期間)ごとにPBI・SBIを取る SBIタスクは必ずPBIに紐づけられている必要がある SBIにはタスクの見積もりとしてポイントを振る スプリント期間中はSBIのタスクの進捗状況に合わせてステータスを変更する また、基本的なカンバンボード以外に、自動化で実現したいことを以下としてみます。 PBI側のDBからSBIの情報をまとめて集計したい 完了したSBIの消化ポイント数 着手中のPBIの達成率 スプリント期間が変わったり、進めているタスクが取り下げになったり、といった急な状況にも柔軟に対応したい SBIの情報を元にPBIのスプリント期間を自動連携 SBIの情報を元にPBIのステータスを自動連携 PBI・SBIの作成 まずは以下のようなNotionDBを3つ用意します PBI管理用DB SBI管理用DB スプリント期間管理用DB 日付プロパティを追加し期間を追加します。 次に、カンバンボードとして扱うためのSBIのステータスを、以下のように4種類定義してみます。 未着手 保留 進行中 完了 連携方法 NotionDBには「 リレーションとロールアップ 」というDB間の連携に便利な機能があるので、基本的にはこれを使っていきます。詳細はNotionの ドキュメント をご参考にしてください。 PBIとSBIのタスクを連携してみる まずは、スプリントごとに着手するSBIの情報を知りたいので「SBI」と「スプリント期間」のDBをリレーションで紐づけます。 同様に、タスクの紐づけを行うためにSBIとPBIにもリレーションを貼っておきます。双方向でリレーションを貼っておくとPBI側のDBからも操作できるのでいい感じです。 最低限のカンバンボードとしては機能しますが、更に自動化するために以下を行いました。 SBIのポイントをPBIで合算してみる PBIに紐づくSBIのポイントを集計し、PBIごとの達成率を表示させます。 以下のように、SBIのDBにタスクに対するポイントの見積もりを入れるプロパティを追加し数値を入れます。 ここまででSBIのポイント算出はできましたが、PBI側のポイントはまだ分かりません。そこでSBIのポイントをPBI側で集計できるようにしてみます。 PBIのDBでロールアップを追加し、SBIのDBをリレーションとして選択します。さらに、ロールアップ内で見積もりをプロパティとして指定し、計算から合計を選択すれば完了です。 PBIの完了割合を算出してみる PBIのポイントの算出は出来ましたが、これだと全体のポイントの母数がわかるだけなので、今どのくらいSBIが進んでいるのかといった進捗具合は何も分かりません。 ここでは無理やりSBIのステータスをロールアップで個別に取得し、PBIの完了割合を算出しようと思います。 まずは、SBIのDBにポイント算出用の関数プロパティを2つ追加します ポイント算出用(合計) if(prop("ステータス") != "取り下げ", prop("見積もり"), 0) ポイント算出用(完了) if(prop("ステータス") == "完了", prop("見積もり"), 0) PBIでは以下のように、SBIで定義した値のロールアップを追加します。 ポイント(全体) ポイント(完了) さらに、PBI側でポイントの完了割合を可視化してみます。 参考までにコードは以下のようにしてみました。関数プロパティを2つ追加しています。 ポイント計算用 prop("ポイント(完了)") / prop("ポイント(全体)") 完了割合 slice("▓▓▓▓▓▓▓▓▓▓", 0, round(prop("ポイント計算用") * 10)) + slice("░░░░░░░░░░", 0, 10 - round(prop("ポイント計算用") * 10)) + " " + format(round(prop("ポイント計算用") * 100)) + "%" + "(" + format(prop("ポイント(完了)")) + "/" + format(prop("ポイント(全体)")) + "pt)" PBI側でスプリントを管理する ここまでの操作で既にSBIでは、以下のようにスプリント期間でフィルターを行いどのタスクをどのスプリント期間内で行うのか、ということが一目で分かるようになったはずです。 とはいえ、似たようなビューがたくさんある場合、スプリント期間が変わる度にフィルターをわざわざ張り替えるは面倒です。それを避けるために、まずは現在のスプリント期間を算出できるようにします。 スプリント期間のDBに、以下のような3つの関数プロパティを追加します。 開始日 start(prop("期間")) 終了日 end(prop("期間")) 現在のスプリントフラグ if(dateBetween(prop("終了日"), now(), "hours") > -24 and dateBetween(prop("開始日"), now(), "hours") < 0, true, false) SBIと連携させるため、SBIのDB以下のようなプロパティを追加します。 現行スプリント(ロールアップ) リレーション:スプリント プロパティ:現在のスプリントフラグ 計算:オリジナルを表示 現行スプリント(SBI) contains(prop("現行スプリント(ロールアップ)"), "Yes") すると以下のようになるはずです。 これで、今現在の日時を比較して現在のスプリントをフィルターできるようになりました。 ですが、SBIに紐づけたスプリント期間の情報をPBIへは何も渡していないので、PBIのみで進捗を把握したい場合などでは不便です。そこでスプリント期間もPBI、SBI間で自動連携できるように、PBIでロールアップを2つ追加します。 スプリント(PBI) リレーション:SBI プロパティ:スプリント 計算:オリジナルを表示する 現行スプリント(PBI) リレーション:SBI プロパティ:現行スプリント(SBI) 計算:オリジナルを表示する これで、PBI側のDBでもスプリント期間を指定してフィルターできるようになりました。 SBIとPBIのステタータス自動連携 最後にこの記事の本題でもある、「SBIとPBIのステータスを自動連携する方法」について考えてみます。 ここまでの操作で、SBIのDBではステータスを管理できているので、ロールアップなどを用いてPBI側とステータスも連携させてしまえば良さそうです。 ということで、まずはステータスを取得するためのロールアップをPBIのDBに追加します。 ステータス(ロールアップ) リレーション:SBI プロパティ:ステータス 計算:オリジナルを表示する これで、SBI側のステータスを全て取得することができました。 ただこの状態だと1つのPBIに複数のSBIが紐付けられている場合は上手くフィルターできないので、どれか一つのステータスに絞る必要がありそうです。 そこで、ステータスを自動算出するための関数プロパティを追加します。 PBIで管理するステータスは、一旦SBIと同じ4種類とします。 ステータス(自動連携) if(or(contains(prop("ステータス(ロールアップ)"), "着手中"), and(contains(prop("ステータス(ロールアップ)"), "完了"), contains(prop("ステータス(ロールアップ)"), "未着手"))), " 着手中", if(and(contains(prop("ステータス(ロールアップ)"), "完了"), not contains(prop("ステータス(ロールアップ)"), "未着手")), if(not contains(prop("ステータス(ロールアップ)"), "保留"), " 完了", " 保留"), " 未着手")) 残念ながらNotionの関数ではswitch文などが使えないので、無理やりこのようなif文で算出しました。 式のみだと分かりづらいので、関数式の説明を以下に書いておきます。このあたりはプロジェクトごと管理方法に合わせてカスタマイズすると良さそうです。 着手中 紐づくSBIのうち1つでも「着手中」が存在していれば反映される もしくは「着手中」が存在しない場合でも、紐づくSBIに一部でも「完了」が存在していれば反映される 完了 紐づくSBIが全て「完了」になっていれば反映される 保留 紐づくSBIに「未着手」「着手中」が存在せず、他全てが「完了」「保留」である場合のみに反映される 未着手 紐づくSBIが全て「未着手」、もしくは紐づくSBIが存在しない場合に反映される 成果物 色々詰め込んでしまいましたが、これで「ステータス」「スプリント」「ポイント」が自動連携されたカンバンボードの作成が完了したと思います。 この状態でPBIのボードビューから「ステータス(自動連携)」でグループ化を行うと、以下のような表示になります。 まとめ 今回は、NotionDBを用いたカンバンボードの自動連携について紹介しました。 これはカンバンボードの作成に限らずですが、実際にやってみた感想として、NotionDBを用いた改善では「試しに触ってみて少しづつ理解しながら改善していく」という形を取るのが良いのかなと感じました。 実際、業務で取り組む際には「こういう機能があったらいいな〜」といった疑問や、開発メンバーの意見なども取り入れながら少しづつカンバンボードに反映させていく…という手法を取っていました。結果的に、遠回りにはなりましたがNotion自体の機能や自動化の勘所など、多くの学びが得られたなと思います。 ただし、NotionDBにはリレーションを追加すると動作が重くなってしまう…という問題があるため、実際の改善でもこれ大きくぶち当たりました…。もし、自動化を試すのであれば「チームメンバーのPCのスペックとも相談しながらあまり機能を詰め込みすぎないようする」といった工夫が必要になってくるかと思います! カンバンボードに限らず、NotionDBを使って何かを自動化をするための参考に少しでもなれば嬉しいです。 参考記事 https://www.notion.so/product We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに はじめまして。ニフティでインフラエンジニアをしている横山です。 自身が担当しているシステムの一部にVDI環境があり移動ユーザープロファイルの機能を利用しているのですが業務効率の低下につながる課題を抱えております。そんな中、課題解決につながりそうなソリューションとしてFSLogixに興味を持ちまして実際に利用してみました。 用語について VDIとは? 仮想デスクトップ(Virtual Desktop Infrastructure)を指します。ユーザーが利用するPC端末のデスクトップ環境をサーバ上で一元管理する仕組みを指します。従来の環境と比べてセキュリティ対策やコスト削減などのメリットがあります。 ユーザプロファイルとは? ユーザ個人のファイルや設定などが保存されたもので、下記の例ではWindowsクライアントへアクセスした際にYokoyamaというユーザでアクセスすると、Yokoyamaフォルダをユーザプロファイルとして利用することができます。このフォルダ群をユーザプロファイルと呼んでいます。 移動ユーザープロファイルとは? 複数のコンピューター間でユーザの設定やカスタマイズ、個人データを移動させるための機能です。VDI環境では仮想マシン上でユーザーの仮想デスクトップが実行されますが、ユーザが異なるコンピューターで作業する際に一貫性のある環境と個人設定を提供するためこの機能を用います。一般的にフォルダリダイレクトと組み合わせて使うことが多いかと思います。 抱えている課題 移動ユーザープロファイルは端末へログインする際、ファイルサーバに格納されているユーザプロファイルを端末にダウンロードしますが、ダウンロードが完全に終わるまでログインが完了することはありません。そのため大多数のユーザが同タイミングで一斉にログインしたり、ファイルサーバ側にサイズの大きなファイル等がある場合にサーバへの負荷が集中してしまい、VDI端末を利用するまでにユーザーはかなり待たさせることになります。 こうしたI/O集中などのサーバへの負荷によりログインストームと呼ばれる状態が起きることがあり、業務のレスポンス低下を招いていました。何か手立てはないか考えていたところFSLogixというソリューションがあることを知りました。 FSLogixについて FSLogixは仮想デスクトップ環境や仮想アプリケーション環境において、ユーザのプロファイルデータとアプリケーションデータを効率的に管理するためのソフトウェアです。今回はFSLogixの提供している機能の一つであるプロファイルコンテナについて触れていきます。 プロファイルコンテナはユーザプロファイルをコンテナ化しマウントする仕組みになります。コンテナ化されたファイル(VHDX)はファイルサーバ等のストレージへ保存することができ、ユーザのログイン時においては該当するVHDXファイルをマウントして利用する形になります。 ※コンテナ化 = アプリケーションやサービスを実行するための環境をパッケージ化したものです。 ファイルサーバから端末に対してファイルのダウンロードを行う移動ユーザプロファイルに対して、ユーザプロファイルを直接マウントするFSLogixでは後者のほうがかなりの 速度向上 を見込めるのではないかということで実際に検証してみることにしました。 検証内容 FSLogix(Profile Container)利用と従来の移動ユーザープロファイル利用時のパターンにおいて、ログイン/ログオフの速度やアクセス先のファイルサーバへの負荷等を検証してみます。 検証環境 役割 OS スペック(CPU / メモリ / ディスク) 台数 VDI端末 Windows10 4CPU / 16GB / 80GB 10 ファイルサーバ Windows Server 2022 2CPU / 4GB / 80GB 1 Active Directory Windows Server 2022 2CPU / 4GB / 80GB 1 検証方法 ActiveDirectory上に移動プロファイルを利用/FSLogixを利用するための接続するためのユーザをそれぞれ10アカウントずつ作成する。 各アカウントのプロファイルデータには5GB程度のダミーファイルをあらかじめ配置する。 それぞれのパターンの10アカウントで同じタイミングでのVDIクライアント接続を行う。 検証結果 検証パターン ログイン/ログオフ サーバ負荷状況 FSLogix(プロファイルコンテナ) 4秒前後/3秒前後 CPU:3%上昇 メモリ:2~3%上昇 移動ユーザプロファイル 10秒前後/3秒前後 CPU:5%上昇 メモリ:5%程度上昇 ファイルサーバへの負荷はそこまで変わらなかったものの、FSLogixを利用することでクライアントへのログイン速度が格段に速くなりました。上述した課題の解決するための手段としてとても実用性を感じる結果になったかと思います。 所感 検証を踏まえて、FSLogixはインストールや設定についても簡単で導入の敷居はとても低いのではないかと感じました。また、今回細かな設定までは触れませんでしたがプロファイルコンテナの設定で1ユーザあたりが作成できるファイルサイズに制限をかけたり、ユーザープロファイルの格納先を複数指定することが設定一つで行える為、管理者にとってもシンプルで扱いやすいように思えました。今後も提供機能や詳細設定について利用者だけではなく管理者の運用が今以上に楽になるようなものがないかを引き続き調べていきたいと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
こちらは2023年7月に投稿された記事です。 2023年9月以降、ZapierのTwitter連携機能は使用できなくなりましたのでご注意ください。 https://help.zapier.com/hc/en-us/articles/18657531069965 はじめに こんにちは。ニフティ株式会社の並木です。 今回は、Zapierを使ってRSSフィードの更新をトリガーにしたTwitterへの自動投稿機能を作ってみましたので、その方法について紹介いたします。 背景 ブログとTwitterの連携機能が元々用意されていたのですが、そちらが使用できなくなってしまい、ある時期からブログの更新情報をTwitterに手動で投稿していました。 しかし、手作業だとミスする可能性がある&手間もかかるため、RSSフィードの更新をトリガーにして自動化できないかという話になり、Zapierを使って自動化することになりました。 Zapierとは? Zapierとは、複数のアプリ連携し、タスクを自動化するツールです。 今回自動化したいタスクは以下の通りです。 ①ブログの更新を検知したい ②Twitter投稿用のタグを作りたい  ・ブログについているタグと同じタグをTwitterでも付けたい  ・ブログについているタグに半角スペースが入っている場合、Twitterでは取り除きたい ③Twitter投稿用のタグに「#」を付けたい ④以下の形式でTwitterに文章を投稿したい ブログを更新しました! 今回の記事は「〇〇」です。 https://engineering.nifty.co.jp/blog/xxxxxxx #タグ #タグ #タグ ①ブログの更新を検知したい トリガーの設定をします。 Appは「RSS by Zapier」、Eventは「New Items in Multiple Feeds」を選択します。 FeedsURLsには、RSSフィードURLを設定します。 ②Twitter投稿用のタグを作りたい ブログについているタグを取得し、半角スペースが入っている場合は取り除きます。 Appは「Formatter by Zapier」、Eventは「Text」、Transformは「Replace」を選択します。 Inputで「Raw Category」を選択すると、ブログについているタグを取得できます。 半角スペースの除外をしたいので、Findに「[:space:]」を入力し、Replaceは空のままにします。 ③Twitter投稿用のタグに「#」を付けたい ②で作成したTwitter投稿用のタグに「#」を付け、タグとタグの間に半角スペースを入れます。 Appは「Code by Zapier」、Eventは「Run Python」を選択します。 今回は「Run Python」を選択しましたが、「Run Javascript」を選択すればJavascriptでコードを書くこともできます。 Input Dataの右側の入力ボックスに②で作成したデータを入れ、左側の入力ボックスにキー名を入れます。(以下画像ではキー名を「original_data」としましたが、どんな名前をつけても良いです) Input Dataを用意することで、Codeの中でそれを取り出して使うことができます。 ②で作成したTwitter投稿用のタグに「#」を付け、タグとタグの間に半角スペースを入れる、という処理をPythonで書きます。 できあがったデータ(コード内にある「result」)に対して、「tags」というキー名を付けます。(キー名はどんな名前をつけても良いです) 「output」という辞書型変数に、上記のキー名とデータを設定しておくと、ここで作成したデータを後続の処理で取り出すことができます。 result = "" original_data = input_data['original_data'] tag_list = original_data.split(',') for tag in tag_list: value = "#" + tag + " " result = result + value output = [{'tags':result}] Code by Zapierにおけるデータの渡し方(=「Input Data」及び「output」の使い方)については、公式ドキュメントに詳細が載っています。 https://zapier.com/blog/code-by-zapier-guide/ ④Twitterに文章を投稿したい ブログのタイトル、ブログのURL、③で作成したタグを埋め込み、Twitterに投稿します。 Appは「Twitter」、Eventは「CreateTweet」、Accountで連携したいTwitterのアカウントを選択します。 MessageにTwitterに投稿する文章を入力します。 ブログのタイトル、ブログのURL、③で作成したタグを、文章の中に埋め込んでいきます。 「Should Shorten URLs?」で、URLを短縮化するかどうかを選択することができます。 「false」を選択すると、URLは短縮されずそのまま表示されます。 以上の設定で、RSSフィードの更新をトリガーにしたTwitterへの自動投稿を実現することができました! 感想 Zapierを使用することで、おおむねノーコードで作成できたので、やりたいことを楽に実現することができました。 苦労した点は、③で使用した「Code by Zapier」の書き方について解説されている日本語の記事を探すことができず、「Input Data」及び「output」の使い方を理解するのに時間がかかったことです。 今後Zapierの機能を使う時は、無理に日本語の記事を探すのではなく、困ったらまずは公式ドキュメントを参照しようと思いました。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは、ニフティ株式会社 基幹システムグループの多田 圭佑です。 今回はE2Eテストフレームワークである「Playwright」を使ってテスト自動化をしてみた記事になります。 Playwrightとは Webブラウザのテスト自動化を実行するためのライブラリ 対応ブラウザ:Chromium、WebKit、Firefox、Edgeなど プラットフォーム:Windows、Linux、macOS 言語:TypeScript、JavaScript、Python、.Net、Java ざっくりできること Webブラウザを操作して自動でテストコードを生成してくれる 作成したテストファイルでテスト実行、デバッグ 事前準備 node.js の公式サイトからインストーラーをダウンロードしインストールする 18.17.0LTS(掲載時点のもの) Playwrightを開発プロジェクトのディレクトリ内にインストールする インストール中の確認項目 TypescriptかJavaScriptどちらで使用するか 本記事ではTypeScriptを使用 E2Eテストに使用するディレクトリ名 デフォルトでは「tests」ディレクトリが作成される GitHub Actionsワークフローの追加 デフォルトではfalse ブラウザインストールの有無 デフォルトではtrue npm init playwright@latest 使ってみた 実施環境 windows 10 自動コード作成編 テスト記録 ブラウザ操作ですぐにテストを生成できるツール。 以下のコマンドを実行後にWebサイトを操作するためのブラウザとテストコードをする記録のウィンドウが立ち上がります。 npx playwright codegen ブラウザ この画面で操作した内容がテストコード記録に自動入力される 最初はテストを実施したいURLにアクセスするところから始める テストコード記録 ブラウザで操作した内容が自動でコードとして記録される テストのコピー、クリア、および言語の変更を行うこともできる nifty.comから「nifty engineering」を検索して「nifty engineering」にアクセスする 1.nifty.comにアクセスする 2.「nifty engineering」と入力して検索する 3.検索結果から「NIFTY engineering」を選択する 4.「NIFTY engineering」が表示される 出来上がったコードがこちらとなります。 page:ブラウザのタブ Locator:ページ上の要素(id, nameなど)を取得 getByTestId:テストID(data-testid)で要素を取得 getByRole:要素を役割別に取得 waitForEvent:イベントハンドラーの待機(ex.ポップアップウィンドウなど) import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await page.goto('https://www.nifty.com/'); await page.getByTestId('search-input').click(); await page.getByTestId('search-input').fill('nifty engineering'); await page.getByTestId('search-button').click(); const page1Promise = page.waitForEvent('popup'); await page.getByRole('link', { name: 'NIFTY engineering - ニフティ株式会社のエンジニアたちの ...' }).click(); const page1 = await page1Promise; await page1.getByRole('link', { name: '【6/27(火) 12:00~】スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギを開催します!' }).click(); }); テストファイル作成編 生成されたテストコードを元にtestsディレクトリ配下にテストファイルを作成します。 ( search-test.spec.ts というファイルを作成) テスト実行編 以下の単位でテストを実行することができます。ブラウザは1つから複数で実行できますが、実行中はウィンドウが開かれず、結果のみがターミナルに表示されます。 全てのテストファイル テストファイル単位 テストグループ単位 テスト実行するためには以下コマンドを実行します。 npx playwright test 作成したテストファイルを実行した結果がこちらとなります。 PS C:\workspace\nifty-blog> npx playwright test search-test.spec.ts Running 1 test using 1 worker 1 passed (18.7s) To open last HTML report run: npx playwright show-report PS C:\workspace\nifty-blog> テストが完了すると結果を記す詳細ページが表示されます。 表示されない場合、「npx playwright show-report 」を実行してください。 各テストコードに緑のチェックマークがついています。これはテストが成功したという意味です。 デバッグ編 UI Modeは、テストの作成・実行を視覚的にサポートするためのツールとなります。テストファイルを実行、デバッグした結果をリアルタイムで閲覧することが可能となります。 UI Modeを開くには次のコマンドを実行します。 ※Playwright v1.32.0以上 npx playwright test --ui 赤枠のアイコンを押すことでテスト実行ができます。 ①テストファイル単位 ②テストグループ単位 設定は? playwright.config.ts でテストに関する設定をすることができます。 デフォルトで設定されているブラウザ(projects)はchromium、firefox、webkit(Safari)となっています。 Edgeなど別ブラウザを追加したい場合、projects内に加えてあげる必要があります。 またデフォルトではタイムアウト時間が30秒となっており、時間を変更したい場合は追記する必要があります。(タイムアウトをさせない場合は「0」を設定する) import { defineConfig, devices } from '@playwright/test'; /** * Read environment variables from file. * https://github.com/motdotla/dotenv */ // require('dotenv').config(); /** * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ testDir: './tests', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ retries: process.env.CI ? 2 : 0, /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: 'html', /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://127.0.0.1:3000', /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', }, timeout: 60000, // 60秒 /* Configure projects for major browsers */ projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, ], }); ポイント テストを実施したいファイルを作成したい場合 インストールの際に設定したディレクトリ内にテストファイルを配置する テストファイルの拡張子に「.spec.ts」または「.test.ts」を付ける javascriptの確認ダイアログでどちらを選択したかは自動コード作成では取得できません。 そのため以下のようにコードを追記する必要があります。 // ダイアログで「はい」を選択する dialog.accept(); // ダイアログで「いいえ」を選択する dialog.dismiss(); テストコードの量が増えたらtest.step等で区切って上げた方が可読性が上がります! import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await test.step('nifty.comから「nifty engineering」を検索', async () => { await page.goto('https://www.nifty.com/'); await page.getByTestId('search-input').click(); await page.getByTestId('search-input').fill('nifty engineering'); await page.getByTestId('search-button').click(); }); await test.step('「nifty engineering」にアクセスする', async () => { const page1Promise = page.waitForEvent('popup'); await page.getByRole('link', { name: 'NIFTY engineering - ニフティ株式会社のエンジニアたちの ...' }).click(); const page1 = await page1Promise; await page1.getByRole('link', { name: '【6/27(火) 12:00~】スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギを開催します!' }).click(); }); }); We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。ニフティ株式会社の添野隼矢です。 今回は、ノーコードタスク自動化ツールであるZapierを使って、Notionのデータベースに定期的なタスク(毎月や隔月など)を作成する方法をご紹介します。 上記の作成経緯としては、前にいたチームでNotionのDBを使って仕事をしており、また実施する定例的なタスクも実施するタスクが奇数月と偶数月で異なっていました。 そのような状況により、NotionのDBにアイテムを作成し忘れるということが多々ありましたので、NotionとZapierを使って、定期アイテムを作成するようにしました。 設定方法 毎月の例 ①Zapierにログインし、「Create Zap」でZap作成画面に行きます。 ②Zapの名前を編集します。 今回は、「(毎月)アンケート実施」としました。 ③Triggerの画面でScheduleと検索し、「Schedule by Zapier」を選択します。 ④Schedule by ZapierのEventを選択します。 今回は毎月で作成するため、「Every Month」を選択します。 ⑤日時を設定します。 今回は、1日の9時に動くように設定しました。 ⑥Continueを押し、Test triggerで今日の日付が取れていることを確認します。 ⑦Actionで「Notion」と検索して、「Notion(Latest)」を選択します。 ⑧Eventで「Create Database Item」を選択し、Continueをします。 ⑨「Connect a new account」を選び、定例アイテムを追加したいNotionDBを選択します。 今回は、定例アイテムを追加したいNotionDBとして、「タスク」というDBを作ってそちらを選択しました。 ⑩Databaseの項目に追加したいNotionDBを選び、後は追加したいNotionDBの形式や作業内容に合わせて項目を埋めていきます。(Contentは、Markdown形式で記載ができます) ⑪Contiuneを押すと、Testに進み「Test Action」を実施されます。 実施されると、以下のような画面が出ます。(再度Testを実行したい場合は、Reset actionボタンを押します。) また成功していれば、NotionDBにアイテムが追加されています。 ⑫「Publish」を押す前に、Zapの設定でTimeZoneが「Asia/Tokyo」になっていることを確認します。 ⑬「Publish」を押し、Zap公開すれば完成です。 隔月の例 基本的な流れは、上記の毎月の定例アイテム作成のZapと同じですが、 上記の毎月の定例アイテムのZapに、1個アクション(Filter by Zapier)を追加します。 アクションを追加するところは、TriggerとCreate Database Itemの間です。 Filter by Zapierで以下の条件でフィルターしていきます。 ※フィルターの設定内容 Schedule by Zapierで取得したDate Month(月)を、右に入力した数字とExactly matches(完全一致)比較を行います。 今回は、奇数月に定例アイテムをNotionDBに作成したかったので、右に入力した数字は奇数月の数字を入力しています。 Continueを実行し、「Your Zap  would  have continued」と表示が出て、想定通りの結果になっていれば完了です。 あとはTimeZoneなどを一応確認して、Publishで公開すれば、隔月(例では奇数月)でNotionDBにアイテムが作成されるZapが完成です。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは、ニフティ インフラシステムグループ社内情報システムチームの仲上です。 先日、非エンジニアでもメール配信サービスからAPI経由で情報を取得できるように、Slack boltを使用してbotを作成しました。しかし、情報の取得・整形処理が想定より重く、エラーが頻発するようになってしまいました。その際にlazy listenerを使用してこの問題を解決したことについて紹介しようと思います。 Slack bolt と lazy listener 今回Slack botを作成するにあたって、機能の充実さと導入が容易な点から公式ライブラリのSlack boltを使用しました。 https://slack.dev/bolt-python/ja-jp/tutorial/getting-started Slack boltを使用した場合、Slackへの応答には3秒以内返信という制約があります。処理が重かったり、ネットワークの問題などでレスポンスを返すのに3秒以上かかってしまった場合、Slack側でエラー処理されてしまします。そこでslack boltに搭載されているlazy listener を使用します。この機能を使うことにより、重い処理を非同期で実行できるので、タイムアウトによるエラーを回避することができます。 https://slack.dev/bolt-python/api-docs/slack_bolt/lazy_listener/index.html lazy_listener を使用することで処理結果が出るより先にSlackへの応答を返すことができ、重い処理を非同期で実行することができます。 今回つくったもの メール配信サービス(SendGrid)に登録されている情報をAPI経由で取得し、Slackに表示するbotを作りました。 SendGridとは SendGridとは、クラウドベースのメール配信サービスです。こちらは世界的に利用されている高い到達率を誇るサービスで、APIを叩いてメールを送信することができます。また、SendGridにはテンプレート機能というものがあります。これはメールの送信元や件名、本文などを予め設定しておくことができる機能で、APIのパラメータに本文内の埋め込み情報などを渡すだけで定型文を送ることができます。 今回このテンプレートに登録されている情報を誰でも確認できるようにしたかったため、Slack botを作成しました。 構成図 Slackのグローバルショートカットをクリックするだけで使用できるようにしました。 SlackのショートカットがクリックされるとLambdaがSendGridのAPIを叩きテンプレートに関する情報を取得します。取得した情報はLambdaでSlack用のメッセージに整形され、メッセージが送信されます。 環境 Python 3.9 serverless framework 3.31.0 serverless-python-requirements 6.2.3 aws cli 2.12.4 slack-bolt 1.18.0 slack-sdk 3.21.3 実装 Slack appの登録やLambdaへの登録説明は省略します。 ファイル構成 │ ┣lib #ライブラリ保存用ディレクトリ ┣formatter.py ┣modal.py └sendgrid.py ┣slack #マニュフェスト保存用ディレクトリ ┣manifest-dev.yml └manifest-prod.yml ┣app.py ┣package-lock.json ┣package.json ┣requirements.txt └serverless.yml app.py # Serverless Python Requirements を使用するためにimpoertします try: import unzip_requirements except ImportError: pass import os import logging from datetime import datetime # slack bot関係 from slack_bolt import App, Ack, Say, BoltContext from slack_sdk import WebClient # 独自関数 from lib.formatter import ( format_template_list, format_template_content, ) from lib.sendgrid import ( get_template_list, get_template_id, get_template_content, ) from lib.modal import get_template_detail_modal app = App( # Settings > Basic Information > App Credentials > Signing Secret で取得可能 signing_secret=os.environ.get("SLACK_SIGNING_SECRET"), # Settings > Install App で取得可能 token=os.environ.get("SLACK_BOT_TOKEN"), # AWS Lambdaで動作させるために、以下の設定を有効にします。 process_before_response=True, ) # 登録されているテンプレート一覧(テンプレート名、件名)を返す関数 def post_template_list(body: dict, client: WebClient) -> None: user_id = body["user"]["id"] template_list = get_template_list() templates_length = len(template_list) send_message = format_template_list(template_list) comment = f"<@{user_id}>\\nテンプレートは以下 {templates_length}件 が設定されています" client.files_upload( channels=os.environ["SLACK_CHANNEL"], content=send_message, filename=f"{datetime.now().strftime('%Y%m%d%H%M%S')}_RTMテンプレート一覧.tsv", filetype="tsv", initial_comment=comment, ) # 応答用 def ack(ack, body): ack() # 「realtime-mail-テンプレート一覧取得」が押されたとき、post_template_list を非同期で実行 app.shortcut("get-template-list")(ack=ack, lazy=[post_template_list]) # 「realtime-mail-テンプレート詳細取得」が押されたとき、検索項目入力用のモーダルを表示 @app.shortcut("get-template-detail") def send_modal(ack: Ack, body: dict, client: WebClient): ack() client.views_open(trigger_id=body["trigger_id"], view=get_template_detail_modal()) # モーダルのsubmitボタンが押されたとき、テンプレートの詳細を返す def post_template_details( view: dict, logger: logging.Logger, say: Say, client: WebClient, payload: dict, context: BoltContext, ) -> None: # 入力値の取得 user_id = context.get("user_id", "") inputs = view["state"]["values"] input_value = ( inputs.get("input-block", {}).get("number-input-action", {}).get("value", 0) ) # テンプレートの検索 template_list = get_template_list() template_info = get_template_id(input_value, template_list) template_id = template_info.get("id", "") # テンプレートがなかった場合 if template_id == "": client.chat_postMessage( channel=os.environ["SLACK_CHANNEL"], text=f"""<@{user_id}> 検索内容:{input_value} 検索結果 > 入力された番号で登録されたテンプレートはありませんでした。 """, ) return # テンプレートの内容を取得して変換 template_content = get_template_content(template_id) send_message = format_template_content(template_content, template_id) # テンプレート名を格納 template_name = template_info.get("template_name", "") comment = f"""<@{user_id}> 検索内容:{input_value} 検索結果 > テンプレート番号:{template_name[:4]} > 件名:{send_message.get("subject", "")} > 最終更新日:{send_message.get("updated_at", "")} """ client.files_upload( channels=os.environ["SLACK_CHANNEL"], content=send_message.get("plane_contents", ""), filename=f"{template_name[:4]}_{datetime.now().strftime('%Y%m%d%H%M%S')}.txt", filetype="text", initial_comment=comment, ) # modalのsubmitボタンが押されたとき、post_template_details を非同期で実行します app.view("modal-id")(ack=ack, lazy=[post_template_details]) # アプリを起動します(デバッグ用) if __name__ == "__main__": app.start() # --lamda用の設定 ここから-- from slack_bolt.adapter.aws_lambda import SlackRequestHandler # ロギングを AWS Lambda 向けに初期化します SlackRequestHandler.clear_all_log_handlers() logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG) # AWS Lambda 用handler def handler(event, context): slack_handler = SlackRequestHandler(app=app) return slack_handler.handle(event, context) lasy_listener を使用する際は以下のように書きます。 # app.<アクション>("<modalIDまたはアクションID>")(ack=<ack関数名>, lazy=[<非同期で実行したい関数>]) # ↓はmodalのsubmitボタンが押されたときのアクション app.view("modal-id")(ack=ack, lazy=[post_template_details]) serverless.yaml frameworkVersion: "3" useDotenv: true service: supsys-mailrelay-slackapp provider: name: aws runtime: python3.9 region: ap-northeast-1 iam: role: statements: - Effect: Allow Action: - lambda:InvokeFunction - lambda:InvokeAsync Resource: "*" environment: SERVERLESS_STAGE: ${opt:stage, 'dev'} SLACK_SIGNING_SECRET: ${env:SLACK_SIGNING_SECRET} SLACK_BOT_TOKEN: ${env:SLACK_BOT_TOKEN} SENDGRID_API_KEY: ${env:SENDGRID_API_KEY} SLACK_CHANNEL: ${env:SLACK_CHANNEL} functions: app: handler: app.handler name: supsys-mailrelay-slackapp-${sls:stage} events: - httpApi: path: /slack/events method: post package: patterns: - "!.venv/**" - "!node_modules/**" - "!.idea/**" plugins: - serverless-python-requirements custom: pythonRequirements: zip: true slim: true useDownloadCache: false useStaticCache: false lambdaでは標準搭載されているパッケージ以外は自分で入れる必要があります。これらを手動で行う場合、 パッケージをローカルにダウンロード zipファイルで圧縮 lambdaに転送 と非常に手間がかかります。 そこで serverless-python-requirements を使うことでこれらの手間を低減します。このプラグインは requirements.txt を宣言すると自動でパッケージの圧縮・デプロイまで行ってくれます。 デプロイ $env:SLACK_SIGNING_SECRET='XXXXXXXX' $env:SLACK_BOT_TOKEN='xoxb-XXXXXXXX' $env:SLACK_CHANNEL='XXXXXXXXXXX' # 送信先SlackチャンネルのID $env:SENDGRID_API_KEY='SG.XXXXXX.XXXXXXXXX'D serverless deploy 動作確認 テンプレート一覧 テンプレート一覧を選択します。 登録されているテンプレート一覧がDMで送られてくることが確認できました。 テンプレート詳細 テンプレート詳細を選択します。 表示されたmodalに管理番号を入力して送信します。 DMでテンプレートの内容が送られてくることが確認できました(画像はテスト用テンプレートです) おわりに このbotを開発したことにより、sendgridのアカウントを持っていなくてもSlackからSencGridのテンプレートを見れるようになりました!今までは問い合わせベースで対応していたので、対応の時間を大きく減らすことができました。 Slack bolt + severless framework を使ったbotの開発は非常に柔軟性・拡張性が高いので、みなさんも是非試してみてください! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
ニフティ株式会社に新卒で入社した中井です。 突然ですが皆さん、退勤時の打刻を忘れたことはありませんか?ありますよね。私も入社してすぐの4月でやらかしました 背景 ニフティでは、勤怠管理のWebアプリ上で打刻ボタンを押してから退勤することになっています。私は自分をほとんど信じていないので、業務が終了する時刻に自動的にWebアプリのURLをブラウザを開くよう、Windowsのタスクスケジューラで設定していました。ところが… 起こったこと 研修の関係でいつもより早く業務が終了したので、打刻画面が自動的に表示されるよりも前に、そのままシャットダウンして帰りました。翌日出勤打刻をしようとしたときに前日の退勤打刻を忘れていたことが発覚しました。 私は自分をこれっぽっちも信じられなくなったので、より強力な対策に乗り出すことにしました。 対策 思いついたのは次のような対策です。 退勤画面を開いてシャットダウンするバッチファイルを作成する。 PCをシャットダウンするときは、必ず作成したバッチファイルから行う。 PCの設定を変更し、スタートメニューからシャットダウンできないようにする。 バッチファイルの作成 もともと退勤時刻である17:45に打刻画面を開くように設定していたのですが、実際には早めに業務が終わることもあると思います。本当は退勤したいと思ったとき、つまり、シャットダウンする前に画面を開いてもらうべきではないでしょうか。 しかしシャットダウンイベントをフックするとなると大変ですし、不確実性がだいぶ高くなりそうです。若干使いやすさは落ちますが、一連の動作をバッチファイルにしてしまう方針でいきましょう。 打刻画面を開く ブラウザが閉じたことを確認する shutdown コマンドを発行する @echo off :: 念のため、本当にシャットダウンしたいのか確認する set /p yn_check="Do you want to shutdown? (y/N) >" if not %yn_check:Y=Y% == Y goto end :: 打刻画面を開く start /w {ここに打刻画面のURLを入れます} :: ブラウザが閉じるのを待ちます。 :: とりあえずChromeとFirefoxのプロセスがあるか監視する感じで。 :try powershell sleep 1 tasklist | findstr chrome.exe > NUL if %errorlevel% equ 0 ( echo Google Chrome has not finished, watching... goto try ) tasklist | findstr firefox.exe > NUL if %errorlevel% equ 0 ( echo Firefox has not finished, watching... goto try ) :: ブラウザが閉じたことを確認したらシャットダウンします。 echo Browser has finished. Shutdown 10 seconds later. shutdown /s /t 10 シャットダウンは必ずこのバッチファイルを使うということにすれば解決です。 スタートメニューのシャットダウンを無効化する 単にそういうルールを課すだけというのは、いわゆる「運用でカバー」というやつです。どうせまた普通にシャットダウンしてしまうのが目に見えています。そこで、スタートメニューから電源系のメニュー項目を消してしまいましょう。「ローカル グループ ポリシー エディタ」を使うと達成できます。 この項目を開いて次のように有効化します。 いつものスタートメニューの電源オプションが「現在、利用できる電源オプションはありません。」となり、スタートメニューからシャットダウンできなくなれば成功です。 これで今度こそ「うっかり」はなくなるはずです。 ショートカットをタスクバーに追加 あとはお好みですが、最後の一仕事をしましょう。 作成したバッチファイルはデスクトップに置いておくのでもよいのですが、デスクトップを開かないとシャットダウンできないのもまた不便なので、私は上の画像のようにタスクバーに用意することにしました(一番左のアイコン)。 ただし、バッチファイルをそのままタスクバーにピン止めすることはできないので、ひと工夫が必要です。バッチファイルを実際に実行するのはコマンド プロンプトなので、コマンド プロンプトへのショートカットとして作成することで、この問題を回避することができます。 どこか適当なフォルダで [新規作成] > [ショートカット] から C:\\Windows\\System32\\cmd.exe /c "<バッチファイルのパス>” へのショートカットを作成する。 ショートカットを右クリックしてプロパティを表示し、お好みのアイコンを設定する。 作ったショートカットを右クリックから [タスクバーへピン止めする] を選んで完成。 おわりに 一応まあ、ここまでしても打刻を忘れる可能性があります。シャットダウンせずそのままPCを閉じて帰ってしまう場合です。私は自分を一切信じていないので、ある程度遅い時刻に画面ロック状態に入ったらビープ音を鳴らすという施策も用意しましたが、それはまた別の話としましょう。ただ実際には、ここまでの作業をしたことで打刻のことが頭の中に完全に刷り込まれ、「打刻を忘れてたけどこれのおかげで助かったー」という事案は発生しませんでした。 良かったと言えば良かったのですが、なんとも複雑な気持ちです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も常時受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
お初にお目にかかります。基幹システムグループの桑原です。 システム開発に携わっていれば、多くの方が大なり小なり障害に遭遇しているかと思います。 私も長年開発・運用業務をやっており、システム障害や運用ミスなど、いろんな障害に携わってきました。自分が起こしたり、巻き込まれたりなどなど。 その中から最近発生した、そんなところに原因が・・と思ったもののお話しをします。 障害の概要 ある日お客様への通知物関連の処理にて、お客様の元へ届かないという障害が発生しました。 原因となった該当の処理自体は単純なもので、ファイルをリネームして移動するだけのものでバグが入り込む余地がないほどの処理です。 登場するサーバは下記の2台。 サーバA:ファイルをリネーム・移動する処理が実行されるサーバ 0:30にcron実行される サーバB:移動後のファイルを使用する後続処理が動くサーバ 1:30にcron実行される オマケ情報 サーバAとサーバBは同じNASをマウントしている 時を遡ること約1年、サーバAの処理の終了時間が少しずつ遅れはじめました。 ここからカウントダウンが開始されたのでした。 移動されたファイルのタイムスタンプが今までは0:30だったのが、最終的にリミットの1:30を越えて後続処理に間に合わなくなり、障害の発生。 先に記述したとおり、ファイルをリネーム・移動するだけの処理がなぜこんなに時間がかかるのかまったく理由がわかりませんでした。 調べてみる まずは、サーバAで遅れていった処理のログを見てみました。単純な処理過ぎて使えるログはほぼ出力しておらずまったく役に立ちません。 参考になったのは、ログのタイムスタンプで、0:30となっていたことで、処理自体は時間通りに開始しているらしい点。 移動先のファイルのタイムスタンプを確認してみると、やっぱり開始時間とはかなりかけ離れていることがわかりました。 -rw-r--r-- 1 user1 group1 0 2月 27 01:29 2023 file_20230227.txt -rw-r--r-- 1 user1 group1 0 2月 28 01:29 2023 file_20230228.txt -rw-r--r-- 1 user1 group1 28 3月 1 01:30 2023 file_20230301.txt -rw-r--r-- 1 user1 group1 28 3月 2 01:30 2023 file_20230302.txt -rw-r--r-- 1 user1 group1 84 3月 3 01:30 2023 file_20230303.txt -rw-r--r-- 1 user1 group1 84 3月 4 01:30 2023 file_20230304.txt -rw-r--r-- 1 user1 group1 28 3月 5 01:30 2023 file_20230305.txt -rw-r--r-- 1 user1 group1 0 3月 6 01:31 2023 file_20230306.txt ←この日から障害 -rw-r--r-- 1 user1 group1 0 3月 7 01:31 2023 file_20230307.txt -rw-r--r-- 1 user1 group1 28 3月 8 01:31 2023 file_20230308.txt なぜこの処理でこんなに時間がかかるのか、ソースを見ても時間のかかるところなんてありませんでした。 ファイルサイズは0~100byte前後がほとんどで普通に考えれば一瞬で終わります。 そしてさらに謎なことに、10日程度でこれがおさまったことです。 ちなみに3月15、16日はなにもしていません。 -rw-r--r-- 1 user1 group1 28 3月 14 01:32 2023 file_20230314.txt -rw-r--r-- 1 user1 group1 56 3月 15 01:33 2023 file_20230315.txt -rw-r--r-- 1 user1 group1 28 3月 16 00:30 2023 file_20230316.txt ←0:30に戻る -rw-r--r-- 1 user1 group1 84 3月 17 00:30 2023 file_20230317.txt -rw-r--r-- 1 user1 group1 56 3月 18 00:30 2023 file_20230318.txt -rw-r--r-- 1 user1 group1 56 3月 19 00:30 2023 file_20230319.txt -rw-r--r-- 1 user1 group1 28 3月 20 00:31 2023 file_20230320.txt ←また遅れ始めた -rw-r--r-- 1 user1 group1 252 3月 21 00:31 2023 file_20230321.txt その後また少しずつ遅れ始めていて、このままではまた1年後くらいに同じことが起こってしまう可能性がありました。 調査に行き詰まり、チームでの障害共有のときに何かとっかかりになるような観点ないか相談をしてみました。 解決 結果からいうと、処理に時間がかかっていたわけではなく、サーバAの時計が遅れていました。 約1年前から少しずつ時計が遅れていき、後続処理までの1時間を超えてしまったというオチでした。 相談したときにNTPでは?と言われ、確認してみたら # vmware-toolbox-cmd timesync status Disable と出てきました。時刻同期が無効だった・・・ そのときのファイルのタイムスタンプと実際の時刻のズレもほぼ同じでしたので、これかと。 なるほど、サーバAではズレている時刻どおり0:30に実行し終わっているので、ログのタイムスタンプは0:30になり、サーバBから見たらファイルは遅れて置かれた時間がタイムスタンプになるわけです。 # vmware-toolbox-cmd timesync enable サーバAで時刻同期を行って対応は終わりました。 他にも時刻同期が無効になっているサーバがないか確認したら数台見つかりました。 しかし、数分のズレで済んでおり、ここまで遅れていったのはサーバAのみでした。なぜこいつだけ・・ それなりに古いシステムで、構築時を思い返しても時刻同期をどうするみたいな細かいところまで手順にはなかった気がします。 約1年前なにがトリガーになって時計遅れ始めたのか、何もしてないのに正しい時刻になおったことなど気になる点はまだありますが、syslog見ても影響していそうなのもなく謎は残りますが、この件は一旦これで終わり。 障害原因の調査をするときは、該当システムばかり調査しがちになりますが、今回のように他のところに問題があることもあるのだなと。 今後の教訓として、迷ったら少しそっちに目を向けた調査も考慮しようと思った一件でした。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。ニフティ株式会社の添野翔太です。 今回はモノレポ用のデプロイパイプラインを構築した話を共有します。 背景 現在、 @niftyトップページ ではアプリケーション基盤の刷新を進めていますが、その過程で一部においてモノレポを採用しています。このリポジトリは、Web3層アーキテクチャにおけるWeb層にあたるもの、App層にあたるもの、およびその他のバッチ処理からなる構成です。 デプロイパイプラインの構築には、Github ActionsとCodeシリーズ(AWS CodePipeline、AWS CodeBuild、AWS CodeDeploy)を利用しています。 モノレポ用のデプロイパイプラインを作ってみる Codeファミリーに関する問題として、一つのパイプラインに対応するブランチが一つしか設定できないという点が挙げられます。 そこで、 Stack OverflowのQ&A を参考にしながら、GitHub Actions上で特定のブランチに強制Pushする機構を作成しました。 まず、ディレクトリ構成を以下に示します。 (Gitリポジトリ) └─.github │ ├─actions │ │ └─applications │ │  └─sample │ │       └─deploy │ │           └─action.yaml │ └─workflows │    └─auto_push.yaml ├─buildspec_app.yaml ├─appspec_app.yaml ├─taskdef_app.json (以下略) 次に、特定のブランチかつ特定のファイルで、Codeシリーズが監視するブランチに強制Pushするコード(.github/workflows/auto_push.yaml)を以下に示します。pathsキーには、主にCodeシリーズで使用するファイル類(BuildSpecやAppSpec、ECSタスク定義など)やデプロイ対象のソースコードを並べます。 name: sample_application_deploy on: # NOTE: PRがマージされた際に動くようにする push: branches: - develop - master paths: - 'buildspec_app.yaml' - 'appspec_app.yaml' - 'taskdef_app.json'             (中略) jobs: development: if: github.ref == 'refs/heads/develop' runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v3 with: ref: develop - name: Deployment uses: ./.github/actions/applications/sample/deploy with: pipeline-branch: pipeline/dev/app production: if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v3 with: ref: master - name: Deployment uses: ./.github/actions/applications/sample/deploy with: pipeline-branch: pipeline/prod/app そして、./.github/actions/applications/sample/deploy/action.yamlに共通処理である強制Pushを行う以下のコードを記載します。 name: auto_push_to_branch description: Auto push to branch inputs: pipeline-branch: required: true description: name of the codepipeline branch runs: using: "composite" steps: - name: Switch branch run: | git fetch --prune git switch -c ${{inputs.pipeline-branch}} shell: bash # NOTE: リポジトリ上でブランチが作られているとpush時にrejectされるためforce pushを実施する - name: Push changes run: | git push origin ${{inputs.pipeline-branch}} --force shell: bash 上記コードのイメージを以下に示します。developブランチとmasterブランチはPRを使用して更新します。PRがマージされると、自動的に別のブランチに強制的にPushされます。強制Pushするブランチ先(pipeline/dev/appブランチとpipeline/prod/appブランチ)は、Codeシリーズを使用して作成するデプロイパイプラインとそれぞれ対応しています。 ここまでApp層のみをデプロイ対象として説明しましたが、Web層をデプロイしたい場合にも同様に展開できます。 おわりに 今回はモノレポ用のデプロイパイプラインを構築した話を紹介しました。何かの参考になれば幸いです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
ニフティ株式会社でシニアエンジニアしています芦川です。 ニフティは他社と比べてトラブルが多いんじゃないか?とか、そういう話ではありません。 これまで「 基幹システムグループ サービスインフラチームの紹介です 」「 目指せ、自己管理型チーム! 役割分担の垣根を取っ払い、心理的安全性を高めるチームマネジメント手法の紹介 」とチーム全体の話を書いてきましたが、今回はエンジニアの学習と成長について私の経験談を通して思っていることを書きます。(長文です。すいません!) この記事を書いたきっかけ 社内では、これからどんなことを学習すればよいのか、どんなときに学習すれば良いのか、学習するモチベーションは何なのか、というような話がよく出ます。私自身はこれまで18年のエンジニア人生を送ってきました。今回のブログでは、どんなとき、どんな感じに私が学習してきたかということと、それらは成長のフレームワーク(コンフォートゾーン、ラーニングゾーン、パニックゾーン)にどんなふうに適合しているのかについて整理してみたいと思い、この記事を書くことにしました。 これからのエンジニア人生が長い人、これからエンジニアを目指す人が読んで、少しでも参考になればいいなと思います。 コンフォートゾーンとは、「居心地のいい場所」。居心地のいい場所に居続けると人間は成長しません。ラーニングゾーンに身を置いた方が人間は成長する、と言われています。 そもそもなぜ学習の必要があるのか? 日々、エンジニアは学習が必要であると言えます。メインのスクリプト言語の変遷でいうと、私が18年前に入社したときに学習したPerlはもう社内では廃れ、その後も、PHP、Rubyと続いてきましたが、今はPythonがメインになっています。しかし、このPythonもより便利で強力なものが出てくれば、いつの日か廃れることは間違いありません。こうした技術的な変遷がある限り学習の必要があります。 そうしたなか、気持ちはいつもポジティブ。学習した分、当然、開発効率があがり、明るい未来があることも経験を通して知っているためです。使いこなせるようになると単純に楽しいし。 余談ですが、「アンラーニング」という言葉がありますよね。これは、特に技術の移り変わりの激しいエンジニアには必要なことかもしれません。 「アンラーニング」(unlearning)とは、いったん学んだ知識や既存の価値観を批判的思考によって意識的に棄て去り、新たに学び直すこと。 引用: アンラーニング 私はいつ学習してきたのか? 私自身は、これまで業務の中で必要に迫られて学習をしてきました。次の業務で使う言語やフレームワーク、クラウドサービスなどについては、主として業務時間内に学習することが多かったです。稀に切羽詰まり、例えば、翌週の火曜日のプランニング(スクラムイベント)で必要なDjango REST Frameworkを知るために、土曜日をまる1日かけて本を完読するような学習をすることもありました。またAWS CDKの初期学習時は、AWS Documentationをスマホでずっと読んだりすることもありました。(スマホで読んだほうがなぜか私は公式ドキュメントが読みやすい。) また思い返してみると、数多くの障害対応、トラブル対応を経験することで、都度、未知の事象を調べ解決していくプロセスが自分の成長に繋がってきたということがあります。前述の学習はある程度のゆとりがある中での学習になりますが、トラブル時は調べないといけない期限が迫っている状態であり、かつ、何を差し置いてもその調査時間をとることになるため、いわば強制的なラーニングゾーンになれる時間です。また、あとから振り返ると、通常での学習では気づけないようなことや観点が経験として学べる、ということが大きかったと思います。ただし、この状況はきつい状況であり、ずっと居続けていてはいけない状態です。幸いにも社風もあるのかこれまで1人でこの状況に居続けることはなく、誰かに相談できたり一緒に解決したり、ということができてきました。結果的に限りなくパニックゾーンに近いラーニングゾーンだったのでしょう。もし解決できないときは、本当にパニックゾーンであり、肉体的、精神的に支障をきたしてしまうのだと思います。 余談ですが、解決できない技術的なトラブルはないと思っています。なぜなら、技術は人の手によって生み出されたもの。なので人の手によって解決できると思っています。ので技術的な課題に対してパニックゾーンに陥る必要はありません。 一方で、業務として必要に迫られてないものや、ちょっと興味がある程度で書籍のみで勉強したことは実は続きませんでした。。。しかし、プライベートで何かアプリケーションやサービスを作ろうと思ったときはその気持ちを優先し、いろいろと作ってきました。このようなときは「学習したい」という気持ちではなく、「作りたい」が先行している状態です。実現したいものが先にある状態。作ることを繰り返していくと、あとから「あー、これを学習したのか」となり、同時に自分に満足なアウトプットが出せるのでハッピーです。こちらは、コンフォートゾーンに近いラーニングゾーンなのかな、と思います。ずっと居たいゾーンですね。 また、どの学習においても、いろいろ自分に取り入れたものを、知ったことを整理し、他者に伝えることで、改めて調べたり、理解が進んだりすることはよくあります。 (まさに、このブログ執筆などもそうです。) 成長のフレームワーク(コンフォートゾーン、ラーニングゾーン、パニックゾーン)に経験をあてはめる 人が成長するのは、3つのゾーンの中で、ラーニングゾーンと言われていますが、さらにラーニングゾーンの中にもレベルがあると言われています。 高ラーニングゾーン パニックゾーンに近いが、ストレス負荷が高めで高成長が期待できる 中ラーニングゾーン その真ん中 低ラーニングゾーン コンフォートゾーンに近いが、ストレス負荷、成長率共に低いが伸びている ここで思ったのは、経験に照らし合わせると、各ラーニングゾーンに達するには、自分から行ける場合もあるし、業務上必要になり、ある意味、強制的に行かされる場合もあるのではないか、ということです。 言い換えれば、実は強制的に、必要に迫られて何かをするほうがが大きく学習できる、つまり身についていく、ということも言えるのではないでしょうか。 さらに言うと、その個人が人から言われなくても、「それが業務上必要である、という認知がどれだけできるか」が、個人の成長スピードにかかっている、とも考えられます。 ここは今回振り返ってみてはじめて気づいた点でした。(エンジニアに限らずとも、どんな職種でもおそらくそうなのでしょうね。) また社内での勉強会や輪読への参加など、学習スケジュールが決められているものに関しても、周囲からの強制力という意味では、真ん中あたりに位置しているのではないかと思います。 つまり、私の経験したことをあてはめると以下のような図ができそうです。外側に行くほど、高成長が期待でき、かつ、(個人の認知の違いはありますが)周囲からの強制力があります。 若くてこれからの人へ トラブルを起こそう、ということではありません。急成長するには、 今ある業務を見渡し必要な学習はすでにやれ、と誰かに迫られていると思ったほうが早く成長できるようになる 、ということだと思います。また、学習スケジュールが決められているものに参加をし 自分にあえて強制をかけていく 、ということも意識するとよいと思います。 で、トラブルが起きてしまったら、 すすんでトラブル対応に関わり普段経験できないことを経験しましょう。 ほかのプロジェクトであってもポストモーテムを読み、自身の経験値として取り入れていくことが大事だと思います。 そして、 モチベーションがあるとき、何かを作りたいと思うときは、贅沢に思う存分プライベートの時間を使い、満足いくまで手を動かし作りましょう! (これが一番楽しい。楽しい、と思う気持ちを大切にしてください。) そして、それらは、すべて他者に何かしらの形で共有し、自身の理解度を高めていきましょう。 以上が、私の経験談を通して、これからの方へ伝えたいことでした!もっと書きたいことがありましたが、長くなりすぎそうだったので、やめておきます!参考になれば幸いです! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
イベントの概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントでは、ニフティグループの社員が業務を通じて学んだことを発信しています! 第11回目のテーマは「 新人エンジニアに贈る最強の開発環境 」です。 ニフティのエンジニアが、働き始めた新人エンジニアに開発環境を紹介する回となります。 【5/30(火) 12:00~】NIFTY Tech Talk 新人エンジニアに贈る最強の開発環境 を開催します! 【LT】Python開発環境 ( 個人的Python開発環境構築 ) Pythonでの開発における便利ツールについて語っていただきました。 チーム開発における品質・生産性向上に効果があります。 Poetry – パッケージ管理ツール Ruff – Linter Black – Formatter Mypy – 静的型チェッカー Pytest – 単体テストツール 資料 【LT】ターミナル・シェルを最強にする話をすると思います 黒い画面の話。 開発環境で使うターミナルやシェルのカスタマイズ、ツール導入について語っていただきました。 iTerm2 設定、カラーなど zsh 高速化 モダンコマンド exa bat navi grex dotfilesのススメ 資料 【LT】StrongestNewsによる最強の自作WEBアプリ開発環境 WEBアプリケーションの開発・環境構築、学習方法・知識の定着プラクティスについて話ていただきました。 StrongestNews(ニュースサイト)はWEBアプリケーションを理解する上で適切で、その後の発展学習にもつながります。 主な技術 React Nginx FastAPI MySQL Docker Terraform Github (Actions) AWS 資料 まとめ 新人向けの最強開発環境ということで、チーム開発を効率化するためのツール活用、エンジニアにとってなくてはならないターミナル、CLIについてカスタマイズ、WEBアプリケーション作成を通じて学習を広げるプラクティスと新人エンジニアには参考になったのではないでしょうか。詳細な資料については以下のリンクから御覧ください。 アーカイブ(YouTube) 発表資料(Speaker Deck) We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も常時受け付けています。 カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは、ニフティのいかりがわです。 ニフティでは毎年、新卒エンジニア向けのOJTとしてエンジニア定例という勉強会を開催しています。 私は機械学習の講師を務めていて、講義の中で Amazon SageMaker を使ったハンズオン実習を行うことにしました。そのために、いろいろな勉強をして準備を進めていました。 その中で、 Amazon SageMaker JumpStart が学習済みのモデルをボタンポチポチで簡単にデプロイできて楽しいなぁと思ったので紹介させていただきます! Amazon SageMaker JumpStartとは まず、Amazon SageMakerを簡単に説明すると以下のようになります。 Amazon SageMaker JumpStartは、Amazonが提供する機械学習のツール 事前準備されたリソースを活用して、目的に合わせた機械学習の実行を容易にしてくれる 機械学習モデルを簡単に作成できるため、モデル開発の経験がない初心者でも簡単に使うことができる Amazon SageMaker JumpStartはAmazon SageMakerの一つの機能である、 Amazon SageMaker Studio から利用することができます。 また、GUIでの操作で簡単に実施することができ、数回のクリックだけで機械学習ソリューションの展開や学習済みモデルのデプロイ、ファインチューニング等を簡単に実行することができます! やりたいこと 今回の記事では以下のことを行います。 SageMaker JumpStartを使うことで、学習済み機械学習モデルを作成、デプロイする! さらに、 Lambda と API Gateway を使って機械学習APIを作成する! SageMaker JumpStartで学習済み機械学習モデルをデプロイする SageMaker Studioを立ち上げるために必要なドメインやユーザープロファイルはすでに設定済みとします。 作成方法は 公式チュートリアル よりご参照ください。 SageMaker Studioの起動 ユーザー名の右側にある、「起動」から「Studio」を選択すると、SageMaker Studioが起動します。 JumpStartを使用して学習済みモデルをデプロイ 1. ホーム画面から、JumpStartを選択します。 2. 使用したい機械学習モデルを選択します。(今回はStable Diffusion 2.1 base) 3. こんな感じの画面に遷移します。 4. 「Deploy」を選択し、デプロイ! 5. モデルとエンドポイントが作成されるまで5~10分ほど待機… しばらく待つと、Endpoint StatusがIn Serviceとなりモデルとエンドポイントが作成されました!(Endpoint nameは後で使います。) API Gateway + Lambdaで機械学習APIを作る Lambdaの作成 1. Lambdaのコンソール画面に移動し、「関数の作成」を選択します。 2. 作成画面では以下のように設定し、それ以外はそのままで「関数の作成」をクリック 。 関数名: 任意 ランタイム: Python 3.10 3. 関数が作成されたら、以下のソースコードをコピペ。 コード内の<エンドポイント名>は、先ほどSageMaker Studioで作成したEndpoint nameを入れてください。 import json import base64 import boto3 # 入力されたテキストデータから機械学習エンドポイントに対して、リクエストを送信し、結果を返す def query_endpoint(text): client = boto3.client('runtime.sagemaker') endpoint_name = '<エンドポイント名>' encoded_text = text.encode("utf-8") response = client.invoke_endpoint(EndpointName=endpoint_name, ContentType='application/x-text', Body=encoded_text, Accept='application/json;jpeg') return response # 機械学習エンドポイントからの出力結果のJSONを解析し、画像を返す def parse_response(query_response): response_dict = json.loads(query_response['Body'].read()) return response_dict['generated_image'] # ここが実行される def lambda_handler(event, context): body = json.loads(event['body']) text = body['text'] response = query_endpoint(text) img = parse_response(response) return { 'statusCode': 200, 'headers': { 'Content-Type': "'image/jpeg'", }, 'body': img, 'isBase64Encoded': True } 4. タイムアウトを5分に設定。 「設定」→「一般設定」→「編集」より設定 できます。 5. IAMロールの変更。 「設定」→ 「アクセス権限」→「実行ロール名」のロール名をクリックすると設定できます 「許可を追加」から「ポリシーをアタッチ」をクリック。 6. 検索フォームから「SageMakerFullAccess」と検索して出てきたポリシーを選択、「許可を追加」で追加し、ポリシーが追加されていることを確認します。 API Gatewayの作成 1. Lambda関数のページから、「トリガーを追加」をクリックし、「ソースを選択」から「API Gateway」を選択します。 2. 以下のように設定し、「追加」をクリック。 インテント: 新規APIを作成 APIタイプ: REST API セキュリティ: APIキー 3. Lambdaの「関数の概要」にAPI Gatewayが追加されていることを確認します。 4. 「設定」→「トリガー」より、API Gatewayが追加されていることを確認し、「APIエンドポイント」と「APIキー」をメモしておきます ローカルで実行! ここまできたらドキドキの実行タイムです! curlコマンドなどでAPIを叩いてみてください! <Stable Diffusionに読ませたい文字>には好きな文字を記述してください 。 curl -X POST <APIエンドポイント> \ -d "{\\"text\\": \\"<Stable Diffusionに読ませたい文字>\\"}" \ --header 'x-api-key:<APIキー>' | base64 -d > ~/Downloads/image.jpeg おわりに 今回は、Amazon SageMaker JumpStartを使用して学習済みの機械学習モデルを作成、デプロイし、LambdaとAPI Gatewayを使って機械学習APIを作成する方法を紹介しました。 Amazon SageMaker JumpStartを使えば機械学習についてあまり詳しくない初心者でも簡単に機械学習のAPIを作成することができます! また、自分で持っている画像を使ってファインチューニングしたモデルを作成することもできますので、機械学習に詳しい方でも色々使えると思いますのでぜひ活用してみてください! 最後に、作成したAPIに「1 pomeranian on the sofa」と入力した結果を貼っておきます! かわいいですね! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
こんにちは! Notion勉強中の小浦です。 他の人が作ったスペースを覗いてみると、見たことない機能を駆使していたりして気になりませんか?私は気になります。 ということで、月に一度開催しているNIFTY Tech TalkでNotionについて話しました! イベントの概要 YouTube Liveにて、ニフティのNotion活用事例について3名が話しました。 詳細についてはこちらの記事をご参照ください。 【4/27(木) 12:00~】NIFTY Tech Talk「【エンジニア必見】Notionで仕事のスピードを加速するテクニックとは?」を開催します! 【LT】世界一利便性が高くてかっこいいプロダクトwikiを目指す Notion愛好家の松阪さんが「世界一利便性が高くてかっこいいプロダクトwikiを目指す」にあたり、重ねてきた工夫について話しました。 実は私のチームのwikiは松阪さんにベースを作ってもらったんです(ニフティの新入社員がいろんなチームを経験できる制度「ジョブローテーション」中に、私のチームに来てくれた時にお願いしました) 進化の過程を3段階に分け、それぞれ工夫したことと改善点を教えてくれました。 DBで何でも作ってしまい、v1で満足している方、多いのでは…(私です) 要素を縦長に並べると間延びしてしまうので、様々なブロックを使ってギュッとまとめたそうです。 特にコールアウトの使い方は目から鱗で、すぐに真似したいと思いました。 【LT】Zapierを使った Google FormsとNotion DBの連携 続いて N1!オートメーションスペシャリストの南川さん 。 Zapierを使って、ノーコードでGoogle Forms → Notionに連携するワザを教えてくれました。 社内で作業依頼をしたり受けたりすることもあるのですが、そんなとき依頼者が直接DBを編集すると予期せぬ編集をされてしまったりするんですよね。 連携の手順を、準備から動作確認までかなり詳しく説明いただきました! 手順通り操作すれば、誰でもできちゃうわけです。しかもノーコードで! Speaker Deckの資料にはもっと詳しい手順が載っていますのでぜひご覧ください。 Zapier初めての方にもおすすめです。 【LT】NotionのWiki機能を使ったページ管理を考えてみる 最後にNotionの運用担当者でもある石川さんのLTです。 最後に N1!プロダクティビティエンジニアの石川さん 。 話題のWiki機能についてのおすすめポイントです。 ページをデータベースアイテムのように扱える 最近追加・編集されたページ一覧が作れる デフォルトでページ配下を検索してくれるボタン Wiki機能を使って、ページツリーとDBのサブアイテムの階層が合っているスペースを作りたい石川さん。 発表資料を作成された時点ではWikiのデータベースプロパティはAPIから変更ができず、代替案で実現したとのことでした。最初はAPIからプロパティの取得もできなかったようですが、現在は可能になっています。今後は変更も可能になっていくのではないでしょうか。日々更新されるNotionに期待しましょう。 まとめ 今回のNIFTY Tech Talkでは、ニフティのエンジニアがNotionの活用事例を紹介しました。すぐに実践できる内容で、私も非常に勉強になりました。ご覧いただいた方が参考にできるものがあれば幸いです。 今後も NIFTY Tech Talk は継続して実施していきますので、ぜひご参加ください。 石川さんがニフティへNotionを導入された時の話はこちらで見られます。 導入を検討されている方、ニフティの社内システムの導入について興味がある方がいらっしゃいましたらぜひご覧ください。 Notion企業活用ウェビナーで「Notion全社導入に伴う移行とデータ整理のノウハウ」というタイトルで登壇しました YouTubeのアーカイブと、発表資料はこちらからご覧になれます。 アーカイブ(YouTube) 発表資料(Speaker Deck) We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに 基幹システムグループ 湊谷です。 突然ですが、皆さんGithub Actionsって使っていますか? GitHub Actions は、ビルド、テスト、デプロイのパイプラインを自動化できる継続的インテグレーションと継続的デリバリー (CI/CD) のプラットフォームです。 リポジトリに対するすべての pull request をビルドしてテストしたり、マージされた pull request を運用環境にデプロイしたりするワークフローを作成できます。 https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions 私の所属しているチームではCI/CDツールとして使ったり、プルリクエスト作成時に自動でテストを走らせたり、Issueを作成したら特定のプロジェクトに紐づけたり、と多くの面で活用しています。 「プルリクエストを作成した時にESLintを実行し、引っかかったらプルリクエストを承認できないようにする」というワークフローを作成していたのですが、一つ気になる点がありました。Github Actionsの仕様として、Warningが出た場合も失敗扱いにはならず、StatusはSuccessとなります。そのため、プルリクエストも承認できてしまいます。 eslintコマンドには –max-warnings というオプションが用意されており、これに0を指定して実行すると「出て良いWarningの数は0=一つもWarningを許容しない」となり、ESLintの実行結果もFailureとなります。 しかし、その様なオプションが無い場合や、Warning以外にも特定の文字列が出力されている時にそれを検知する方法はあるのか?と疑問に思ったため、Github Actionsの中でやる方法を探してみました。 特定の文字列を含む時にエラーになるようにする コードの完成形を見てみます。 name: pr-test on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: npm ci run: npm ci - name: npm run build run: npm run build --if-present - name: npm test run: npm test - name: npm run lint id: lint run: | result=$(npm run lint | tr '\n' ' ') echo "result=$result" >> $GITHUB_OUTPUT echo "$result" | tr ' ' '\n' - name: check lint if: contains(steps.lint.outputs.result, 'Warning') run: | echo 'lintでWarningが出ています。修正をお願いします' exit 1 色々なことをやっていますが、今回関わってくるのは以下の部分です。 - name: npm run lint id: lint run: | result=$(npm run lint | tr '\n' ' ') echo "result=$result" >> $GITHUB_OUTPUT echo "$result" | tr ' ' '\n' - name: check lint if: contains(steps.lint.outputs.result, 'Warning') run: | echo 'lintでWarningが出ています。修正をお願いします' exit 1 まず、 name: npm run lint のジョブではESlintを実行しています。 ESLintを実行した結果をresultに入れます。改行があると最初の一行しか取得できなかったため、改行を無くしています。 result=$(npm run lint | tr '\n' ' ') ESLintの結果を後続のジョブで使うため、 $GITHUB_OUTPUT で値をセットします。 echo "result=$result" >> $GITHUB_OUTPUT そして、ESLintを実行結果も確認したいため、出力します。改行が無いと読みづらいため元に戻しています。 echo "$result" | tr ' ' '\n' 次に、 name: check lint のジョブではESLintの実行結果をチェックしています。 今回は、ESLintの結果にWarningの文字列があったらエラーを返すようにし、ワークフローを失敗としましょう。 contains( search, item )を使います。searchの中にitemがあればtrueを返し、そうでない場合はfalseを返します。 if: contains(steps.lint.outputs.result, 'Warning') 「id:lintで指定したstepsの中のoutputsの中にセットしたresultの値の中にWarningが入っている場合」という条件を設定し、trueであればrun以降書かれた内容を実行します。 今回は「lintでWarningが出ています。修正をお願いします」という文章を出力し、exit 1を実行してジョブを終了させています。 実際に、ESLintを実行した際にWarningが出るようなファイルをわざと用意すると、以下のようになります。 ESLintを実行したところでは失敗とはなりませんが、その後のWarningが含まれているかどうかチェックするところで失敗となり、修正しないとプルリクエストを承認できない状態にできました! 最後に 今回は「特定の要素が含まれているかどうか」をチェックするcontainsを使ってみました。 これを使うと「ブランチ名に特定の文字列が含まれている場合」だけジョブを実行したい、といったこともできそうです。もっとGithub Actionsを活用していきたいです! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
ニフティ株式会社でニフティニュース開発チームでスクラムマスターをやっている中村です。 この記事ではスクラムマスターが身につけるべき新たなスキルとして「動機づけ面接」を紹介します。 (途中のスライドは週次で行っているチーム会の内容からの引用です) スクラムマスターの難しさ 普段は開発チームにおいてスクラムマスターをやっているのですが、スクラムマスターが身につけるべき技術は多岐にわたります。 基本的なコミュニケーションもそうですが、ファシリテーション、コーチング、メンタリング、チームビルディングスキルなどなど、スクラムという枠組みはありながらチームをより良い方向に導くことに最大の責務を持っています。 そして、自分は認定スクラムマスターの資格も保持しているのですが、資格の講習中にこんなことを言われました。 「 スクラムマスターは何も指示しません。 指示をすることはスクラムマスターの責務にはありません。なぜならメンバーが自分で考えて決断できるようにするための役割だからです。」 指示をしないでチームを変える これを聞いた時に自分はこう思いました。 「メンバーが自分で考えて決断できるようにする、という役割は理解できる。でも指示をしないでチームを導けるんだろうか?そもそも人やチームを変えるためには指示に近いことが必要なのでは?」 そんなことを考えていました。 なんとなくはわかるんです。でも、できるとは信じられない。そんな状態でした。 心理療法の世界 話は少し変わりますが、人間の行動を変容させる科学的な技術として心理療法が存在します。 心理療法は1930年代まで「指示的」なカウンセリング手法が主流だったそうです。 相手の言葉の裏を読み取り、そこにカウンセラーが解釈した結果から説得やアドバイスを行う手法です。 しかし、1940年にC.ロジャースという人が「非指示的」な手法を提案します。 これは今日では「来談者中心療法」と呼ばれている心理療法において主流の手法です。 来談者中心療法とスクラム 「来談者中心療法」ではクライアントに対して何か指示することはありません。 人間はみんな「こうなりたい」という願望と現実とのギャップに苦しんでいます。(と考えます) そのギャップが大きくなると問題行動などにつながる、と考えます。 問題と解決策はクライアント自身が知っていて、カウンセラー自身が何かを教える必要はない、というのが「来談者中心療法」の考え方です。 そして、自分はこの説明を読んでいて直感的にこう思いました。 「スクラムマスターがやることってこれでは?」と 動機づけ面接という新時代のスクラムマスターに捧げる武器 「動機づけ面接」はこの来談者中心療法の流れを汲む「非指示型カウンセリング」です。 (行動変容を促すフェーズもあるため、準指示と言われることもあります) 指示をしない方法でありながら、飲酒・ダイエット・喫煙などのあらゆる行動変容の促進に科学的に効果があるとされています。 したがって、スクラムマスターのような「チームをより上手く動かす必要がある」「しかし指示はするのではない」というある種矛盾した立場の人間にとっては、これは必須スキルとも考えられます。 「相手と自分の解釈に違いはないのだろうか?」 「動機づけ面接」は体系化された手法であり、内容が多岐に渡るため、大事な1つの技術としてここでは「聞き返し」のみを取り上げます。 考え方として、私たちは相手が話したことを意識的・無意識的に関わらず、「こういう考えで話しているんだろう」とまとめて意味づけを行おうとします。 そしてこの推測は正しかったり間違ったりもします。 (ある研究によると人の気持ちを推測するテストの正答率は44%らしく、むしろ半分以上は間違っている可能性があります) ここで間違った推測のまま捉え続けてしまうことで、最終的に行き違いやミスコミュニケーションが生まれることになります。 これを乗り越えるために「動機づけ面接」では「聞き返し」によって、相手の意図を確認します。 「あなたが言っていることはこういう意味だと思うが、これで合っていますか?」 というこの意識だけでも、コミュニケーションは円滑になるのではないでしょうか? 「説得」や「指示」をしても人は動かない 自チームのチーム会ではさらに深い考えや手法について解説したのですが、それについてはまた別の記事に記載したいと思います。 自分がこういった方法を調べていて思うことは、結局「説得」や「指示」では人は変わらないし動かないということです。 自分も熱が入ったりすると自分の正当性を主張したくなってしまうのですが、それでは人の抵抗を大きくするだけで、結果的に人に影響をもたらすことは難しくなってしまいます。 そうではなく、相手の思考や価値観・感情も含めて正確に言葉にして理解をしながら、本当の意味で相手を理解するということが重要になるのだなと思います。 自分はスクラムマスターとして「チームを上手く動かすため」「人を理解するため」にこういった勉強を繰り返す傾向にあるのですが、勉強をすればするほど本当に難しいことをしているなと思います。 おわりに 本記事では、スクラムマスターの新しい武器として「動機づけ面接」を紹介しました。 いろんな手法を学び、実験を繰り返して、真のスクラムマスターを目指しましょう。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター
はじめに こんにちは。新卒4年目の南です。 ニフティでは新卒採用活動の一環として、毎年インターンシップを開催しています。 私は2021年・2022年のチーム開発インターンシップにメンター社員として参加し、今年もメンター社員として参加します。 本記事では、今年も開催を予定している「チーム開発3daysコース」について紹介します。 少しでもニフティのインターンシップに興味を持っていただけた方は、是非 登録フォーム からマイページ登録をしていただき、書類提出をお願いいたします! インターンシップについて チーム開発3daysコース概要・応募要項 期間 半日(オリエンテーション)+3日間(プログラム本番) 開催日程(予定) ① オリエンテーション:2023年8月1日(火) 9:00~12:00 プログラム本番 :2023年8月2日(水)~8月4日(金) ② オリエンテーション:2023年8月22日(火) 9:00~12:00 プログラム本番 :2023年8月23日(水)~8月25日(金) ※参加希望日程については①②どちらかを選択いただく形となります。 実施形式 対面実施(新宿本社) ※オリエンテーションにつきましては、オンラインでの実施となります。 応募期間 書類提出〆切につきましては マイページ からご確認をお願いいたします。 参加条件 四年制大学、大学院、専門学校、高専の方(学年不問、文理不問) インターンシップの選考 書類選考あり 大まかなタイムスケジュール 1日目午前 スクラム講義 1日目午後~3日目 サービスサイトの改善課題(スクラム開発) 3日目午後 課題に対する発表/講評 ※いずれの日程も同内容となります。 ※開催日時や応募期間については変更の可能性がありますので、詳細は マイページ をご確認ください。 本インターンシップのおすすめポイント より実務に近いチーム開発を体験できる! 3日間で「スクラム開発」を体験してもらいます。 ニフティでは、スクラム導入の動きが会社全体で高まっており、スクラム開発を行っているチームが10以上存在します。そんなニフティで日々スクラム開発を行っている社員が、講師やメンターとして参加し皆さんのサポートに入ります。 また、スクラム開発での役割は全て学生の皆さんに担当いただきながら3日間の開発を行っていただきます。スクラムについて学びながら、チーム開発を体験できます。 【スクラムとは】 仕事のフレームワークの一つで、アジャイル開発で使われることが多いです。 決まった期間で必ずアウトプットを出す 決まった期間で振り返る などの特徴があります。チームを組んで役割やタスクを分散しつつ、コミュニケーションを取りながら行うので、チーム内のコミュニケーションがより大切になる開発手法です。 詳しくは、インターンシップ1日目に認定スクラムマスター(CSM)の資格を持つ社員から説明させていただきます。 サービスサイトの課題発見と解決に向けた実装に挑戦できる! インターンシップのために用意した架空のサービスサイトの改善を行ってもらいます。 実際にサービスを利用したり設計書などの資料を見ながら、解決すべき課題と改善方法をチームで探り改善に繋げていく流れになります。 仕事をする上で「新しいものを一から作り出す」ということはもちろんありますが、お客様目線を徹底して既存サービスをよりよいものにしていくということが日々の業務に繋がってきます。 別の人が作ったものを改修するということは学校ではなかなかない経験だと思いますので、最初は苦戦するかもしれません。しかし、言語やフレームワークがどのように記述されているのかを知って、スキル向上に繋げることができるいい機会だと思います。 またその中で、どの課題を優先で改善していくのか、改修規模はどのくらいなのか、など様々なことを考慮した上で優先順位をチームで決めて対応してもらいます。 開発スキルはもちろん、仕事をする上で必須となるスキル(タスクの優先順決定など)の向上に繋がるかもしれません。 会社の雰囲気を知ることができる! 今年は、数年ぶりにオフラインで開発インターンシップを開催します。 オンラインとは違い、直接会社の雰囲気を知っていただくことができます。 また、社員とも直接会話・交流が可能ですし、他の参加学生とも交流が可能です。3日目の最後には懇親会も予定しておりますので、この機会に現場社員と就活についてや社内の雰囲気について話して就活の参考にしていただければと思います。 1チーム1人以上の社員がサポートにつく! 各日程どちらもメンター社員6名+講義社員が参加予定です。 そのため、1チーム1人以上の社員がサポートにつく形が実現できます。チーム開発ということで、まずはチーム内で相談いただき解決に向けて動いていただきますが、スクラムに関する質問やチーム内での解決に時間がかかっている場合などは気軽に社員に相談できる環境となっております。 昨年のインターンシップ参加者の感想 インターンシップに参加した学生のみなさんからの感想をいくつかご紹介します。 スクラム開発という経験はなかなかできず、エンジニアを志望する上で必ず体験しておきたかったので、今回参加できてとても嬉しく、楽しく開発を行うことができた。 会社の雰囲気や実際の業務を肌で感じられて充実感のあるインターンシップでした。また、自分の足りていない部分や勉強しなければいけないことが明確になったので、今後の勉強にも役立てていきたいと思います。 文系大学でスクラム開発を行うことは全くないので、その経験自体が貴重な上で更にエンジニアとして働いた時の立ち位置というものをワークを通して理解することができた。 コードが書ければいいというものではなく、リーダーシップや積極性、明るさなども開発の大切な要素だと感じました。 本格的なスクラム開発のやり方やタスクをどのような優先度で行うか、どのようにタスクをこなしていくかという点について、貴社のインターンシップに参加していなったら知らないものばかりでした。 メンター社員の方からエンジニア業務の本音を多く頂くことができたので、実際に働く将来像を見ることができました。 スクラムの流れは授業等で知っていましたが、実際にそれを使って開発できたのが自分にとって1番大きかったです。 人の書いたプログラムから開発するのが初めての経験で大学で勉強したものとのギャップに最初つまずきましたが、日を追うごとにコードの理解度が上がっていき開発スピードが上がっていきました。 チーム開発ももちろんですが、実際の社員の方々の雰囲気を知ることができたことも大きな成果だと感じています。 スクラム開発における成果や実装における成果など様々な感想をいただきました。 また、社員との交流で得られるものに関する感想も多くいただきました。 おわりに ニフティのインターンシップの中でも、自社サービスを提供している会社に興味のある方、システムエンジニアに興味のある方におすすめのコースです。 エンジニアの業務内容について理解を深めていただくことや、チーム開発の楽しさ・難しさを味わっていただけるかと思います。また、このワークを通じてお客様目線を徹底するニフティの風土も感じていただけます! 「スクラム開発、聞いたことはあるけどあまり知らない」「スクラム開発が何かは知ってるけど実践したことがない」という方、多くいらっしゃると思います。是非この機会に、ニフティのチーム開発インターンシップに参加してスクラム開発(チーム開発)を体験してみませんか? 少しでもニフティのインターンシップに興味を持っていただけた方は、是非 登録フォーム からマイページ登録をしていただき、書類提出をお願いいたします! たくさんのご応募お待ちしております。 また、下記の通りニフティではチーム開発3daysコース以外のインターンシップも行っております。 こちら のご応募もお待ちしております。 サイバー攻撃対応コース 企画提案・販売促進体験1dayコース サービス企画・プロモ・マーケ2daysコース We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering
アバター