はじめに マイナビ内でTableau DATA Saber認定制度に挑戦された3名に、師匠(前編)・弟子(後編)それぞれの立場で2作に分けて体験記を書いていただきました。 本記事では後編・弟子についてお届けします。前編・師匠については こちら をご覧ください。 自己紹介 ご覧いただきありがとうございます。データソリューション統括部 データ活用推進1課のT・SとS・Sです。2023年2月からTableau DATA SABERプログラムに挑戦し、無事4月にDATA SABERに認定されました。 この記事ではTableau DATA SABERプログラムに挑戦していた時のことを回顧してみようと思います! そもそもDATA SABERとは? Tableauの技術はもちろんのこと、データのその先の世界を見通す技術力とデータドリブン文化を伝え、人々を導く力を身につける資格/制度です。 DATA SABERを目指す者は3か月間の限られた時間の中、 Tableauの技術力を磨くための十の試練 導く力を鍛えるための、コミュニティ活動(社内外でデータドリブン文化を広めるための活動) を行い、全てクリア/最後の試験を突破したものに与えられる称号となります。 (これをクリアするために3ヶ月で100時間以上の勉強時間が必要になります。) 1日1~2時間ペースで勉強をすればいいように見えますが、通常業務にプラスで時間をかけて勉強をしなければいけないので、大変な試練であることはお伝えしておきます。 詳しくは 公式HP をご確認ください それぞれの回顧録 T・SとS・S、それぞれがDATA SABERプログラムで過ごしてきた時間が異なります。 そのため、それぞれの歩んできた道を書いていこうと思います。 CASE 1 T・Sの場合 改めて自己紹介 私立大学文系学部卒。 「システムエンジニアってなんですか?」というレベルで、この業界に足を踏み入れました。 新卒1年目でSESの会社に就職し、某携帯電話キャリア会社に客先常駐。そこでBIについて色々と学びました。 新卒3年目の途中にマイナビに転職し、それからはBI開発に携わったり、現在ではセルフBIの導入、サポートなどを業務として行っています。 DATA SABERチャレンジ前のTableau歴・レベル DATA SABERチャレンジ前のTableau歴:4年ほど レベル:簡単なグラフや集計表とそれを組み合わせたダッシュボードが作れるレベル 初めてTableauに出会ったのが、某携帯電話キャリア会社で客先常駐していたころになります。 当時、新卒2年目の時に初めてTableauを触りました。そのころは簡単なグラフや集計表を作る程度で、ダッシュボードを開発したりなどのスキルは持ち合わせていませんでした。 マイナビに転職してからもしばらくはTableauは触っておらず、 2021年10月の部署異動を機に、久しぶりにTableauを触り、そこからは独学でTableauについて学んでいったというレベルになります。 独学だったため、Tableauの機能をちゃんと理解しているわけでもなく、有効活用もうまくできていませんでした。 チャレンジした経緯 簡単に言うと、Tableauのスキル・技術を身に着けるためです。 異動してから、Tableauでダッシュボードを作成する業務が発生しました。しかし、自分の知識不足のせいか、Tableauの機能を最大限に活かせていないと感じ、DATA SABERに挑戦しました。 また、同時に私はデータドリブン文化を社内に根付かせる部署に所属しています。Tableauのスキルや知識を他の方に展開する立場であるのに、Tableauの機能を活かせていない、機能を知らないのは、データドリブン文化を根付かせるうえで今後障壁になるのではないかと思いチャレンジしました。 弟子時代に取り組んだこと Tableauの技術力を磨くための十の試練 こちらについては与えられた問題に対して回答するものになります。 内容は、①tableauをつかってデータを可視化し回答を探し出すという問題と、②データドリブン文化を広めていく上でどのような考えでどのような行動を取ったらいいかを問われる問題と2パターンあります。 どちらも全問正解しないとCLEARにはならない課題です。 ①の問題例は こちら ②の問題例は こちら ①については技術力が問われる問題であるため、自分が持ち合わせている知識を使ったり、わからないものについては、別途、勉強動画を見たりして知識を習得しました。 ②については、どちらかというとデータドリブン文化を作る上で必要なマインドや考えを問われるものになります。そのため、答えを導くために一緒に挑戦していたS・Sさんとディスカッションしたり、師匠とディスカッションなどをして答えを導いてきました。 技術力を磨くための試練とあるように、知識や考えを問われる問題であるため、わからないものは素直にわからないと認めて、勉強動画をみたり師匠などとディスカッションを重ねたりしました。 導く力を鍛えるための、コミュニティ活動(社内外でデータドリブン文化を広めるための活動) いくつかお題が設定されており、そのお題ごとに取得できるポイントが決まっています。社内、社外それぞれ20ポイント、合計50ポイント取得してCLEARとなる課題です。 私が行った取り組みを社内向け、社外向けでいくつかご紹介します。 【社内向け】 Tableau Doctor Tableauを社内で利用している方々の悩みや、こんなことを実現したいという要望を聞いて、どのように解決すればいいかを提示するものになります。 悩みや実現したいことの内容は様々ですが、社内のユーザーがどんなことに躓いているのかがわかったり、またその悩みに対してデータ活用推進部署としてどのような施策を打つと良いのかなどを考えるきっかけになりました。 この取り組みは、最初はDATA SABERの時だけ開催しようとしていたのですが、社内のTableauユーザーから好評でありましたため、上長と相談し、月2回開催できるようにしました。 Tableau勉強会「Tableauにおけるパフォーマンス改善」 社内全体でTableauを利用する上での課題で、Tableau ServerのCPUやメモリの使用率が逼迫してしまい、大規模障害発生につながってしまう恐れがあるという課題がありました。この事象が発生する原因の一つとして、ユーザーがTableau Serverに負荷をかけやすいダッシュボードを作っていることがあげられていました。 ですが、Tableau Serverに負荷をかけにくいダッシュボードの作り方をユーザーが知らないということが根本原因でありますため、「ユーザーの皆さんでもすぐに改善できる」というポイントを中心に、勉強会ではお話しました。 その結果、早速パフォーマンスをよくするために、作ったダッシュボードの改善に取り掛かってくれるユーザーが出てきたり、新規作成する際にも、勉強会でお話したポイントを頭に入れてダッシュボードを作ってもらったりなど、社内で少しずつ改善する動きが起こるようになりました。 【社外向け】 Tableauに関するブログ記事の投稿 Tableauに関するブログ記事をいくつか投稿しました。 Tableau Serverのリポジトリについて TableauにはTableau Serverという、作成したダッシュボードを共有するWebアプリケーションツールがあります。その裏にはアクセスデータなどが蓄積されていまして、裏にはどんなデータがあるのかだったり、そのデータの活用事例などをまとめたものになります。 DATA SABER見習いがTableauを使っていて思うこと DATA SABERのプログラムを進めていく中で、Tableauに関する色んな知識、表現技法を習得しました。ですが、どんなに凝ったものを作ったとしても、見る人が正確にデータを読み取れないと意味がないと考えています。「見る人第一のダッシュボードを作りましょう」という自分への戒めの意味も込めた記事になっています。 Visual Analyticsについて こちらは、DATA SABERの課題で私が苦手に感じていた部分をまとめたものになります。データに応じた最適な表現の仕方や、色や形などの人間が無意識に把握できるものを効果的に利用すると、わかりやすいダッシュボードが作成できるということを記事にしています。 Tableau DATA SABERになったので、自分なりの勉強法書いてみる こちらはDATA SABERになった後に書きました。私がDATA SABERにチャレンジしていた際に、どのように勉強を進めていけばいいか悩んでいる時期がありました。そんな私と同じ悩みを持っている方々に向けて、道しるべになればと思い書いた記事になります。 このようにして、DATA SABERで学んだこと、気づいたことなどを、社内だけでなく社外にも展開してきました。 今後もマイナビのDATA SABERとして、データ活用に関する情報発信を実施していけたらと考えています。 苦労したこと 一つ目は時間のやりくりです。 私がDATA SABERにチャレンジしている期間は、通常業務も繁忙期でありまして、学習時間を割けられない日もありました。そのため、上長に許可を得て残業して学習時間を得たり、何とかしてDATA SABERの試練にチャレンジするための時間を得ていました。 また、動画で勉強することもできるのですが、通勤時間に動画を見たり、隙間時間などを勉強に活用していました。 二つ目はデータドリブン文化を作る上でのマインドなどを問われる問題について、何度もやり直しを食らったことです。 tableauをつかってデータを可視化し回答を探し出すという問題とは異なり、この問題はDATA SABERが持つべきマインドを問われるため、DATA SABERのことをちゃんと理解していないといけません。 何度も躓きはしましたが、一緒に挑戦していたS・Sさんと意見交換をしたり、師匠とディスカッションしたりなどを行うことで、DATA SABERとしてのマインドが少しずつ分かるようになってきました。そしてこのマインドこそが、マイナビ社内にはまだまだ足りていないものであり、データドリブンを推進する立場である私自身にも不足していたものであることを痛感しました。 このような苦労はたくさんありましたが、それを乗り越えたが故に、自信につながったかなと今では思っています。 学んだこと Tableauに関するスキルについてはもちろん多くの学びがあったのですが、一番はDATA SABERとして、データドリブン文化を根付かせるためにはどのように行動をすべきなのか、その姿勢や行動指針について学ぶことが多かったと思います。 今までの自分はデータ活用を推進する部門に所属していたものの、ユーザーから来た質問に対して答えたり、データ分析基盤の構築案件で任されたタスクに注力していたりしていました。これらの業務も勿論大切な業務ですが、DATA SABERの試練では 「自分から能動的に動く重要さ」 を学びました。今までの自分はどこか受動的な側面がありましたが、DATA SABERは データドリブン文化を創造する、浸透させる ことが使命です。 受け身の姿勢でいるだけでは、キャッチアップできる社内のデータ活用の課題や悩みなどは氷山の一角に過ぎないですし、データドリブン文化を推進する立場である人間が受け身の姿勢でいては、データドリブン文化はいつまでたっても生まれないと実感しました。 この学びがあったからこそ、最初はDATA SABERの活動の一貫として行っていたデータ活用相談会を、自分が上長に進言して今も継続して活動を実施したりなど、自分自身少しだけ能動的に行動を起こせるようになりました。 これからもこの学びを大事にし、DATA SABERとして能動的にアクションを起こし、データドリブン文化を根付かせていきたいと思っています。 今後のこと DATA SABERとして、データドリブン文化を根付かせるための活動を進めていきたいと考えています。社内外問わずとは考えていますが、まずは社内から根付かせて行けたらと思っています。 そのためには精力的に活動を行い実績を積み、社内にDATA SABERを認知してもらわないといけません。 まずは、データ活用相談会など、引き続きできることを地道に実施を行っていきながら、社内のデータ活用ユーザーと接点を作っていき、少しずつDATA SABERを認知してもらえるようにできたらいいなと思っています。 また、社内にインパクトを与えられるような取り組みも認知には必要かと思っています。ですので、社内でまだ誰も取り組めていないデータ活用のスキルベルト作成の検討も今後行いたいと考えています。 そして、私が今度は師匠となってDATA SABERを育成し、各事業部門でデータ活用が自走できる世界観を作っていけるようにしていきたいと思います。 CASE 2 S・Sの場合 自己紹介 私立大学理工学部数学科卒。 理工学部と聞くと一通りPC操作には慣れている印象を持たれますが、大学時代では採用活動でのESとレポート作成でしかPCを使わなかったくらいの初学者で入社しました。 2022年4月にマイナビに入社し、10月までは技術研修や社内インターンシップを行いました。 2022年10月にT・Sさんと同じ課に配属され、社内のデータ活用基盤の保守運用とデータ活用推進やデータ民主化を主な業務としています。 DATA SABERチャレンジ前のTableau歴・レベル DATA SABERチャレンジ前のTableau歴:2ヶ月 レベル:BIツールがどのような目的で利用されており、Tableauが社内でどのように活用されているのか知っている状態。 2022年8月に社内インターンシップ内でTableauのハンズオンを体験させていただく機会があり、そちらでTableauの存在を知りました。(インターンシップ担当はT・Sさんでした) 2022年10月の配属後に自身の課が行っているTableauの導入相談や利用推進のミーティングに同席するようになったため、Tableauの特徴や役割を知るようになりました。 TableauはセルフBIツールとして現場に提供しており、部署のメイン業務としてダッシュボード作成を行うわけではないため、利用経験はほとんどありませんでした。 チャレンジした経緯 そのままですが、Tableauの知見を増やすためです。 データ活用相談で課の一員として貢献するためにもTableauの知見は必須でした。 ユーザーサポートも一人では行えない状況であったため、Udemyなどを活用して学習を始めた段階でした。 また、社内のTableau利用を推進する為にTableau社主催のイベントに参加し他社事例を伺う機会もありましたが、その際にDATA Saberについての話も耳にすることが多くありました。 学習するなら資格取得という明確な目標を持って取り組んだ方が良いと考えチャレンジを決意しました。 弟子時代に取り組んだこと Tableauの技術力を磨くための十の試練 こちらについてはT・Sさんと同様のため割愛させていただきます。 導く力を鍛えるための、コミュニティ活動(社内外でデータドリブン文化を広めるための活動 ) T・Sさん同様に社内、社外に向けた取り組みを行いました。 【社内向け】 DocBaseによる情報共有 社内のドキュメント共有ツールであるDocBaseにてTableauのTipsをアップしました。 具体的には、細かなフィルターアクションの設定方法や二重軸の設定方法、ウォーターフォールチャートの紹介など知っているからこそ活用できるTableauの機能や活用方法についてご紹介しました。 【社外向け】 Tableau PublicへのVizの投稿 Tableau Publicとは世界中の方がだれでも自身で作成したVizを共有することができるTableauのサイトです。 私は趣味である、海外サッカーについてのデータの可視化を行いました。 ここで自身が作成したVizを共有する事の意義は、単にアイディアを発信するだけでなく、新たな繋がりを作る事ができる点にあります。 私もここでコミュニケーションをとった方のVizから学びを得る機会となりました。 Tableau関連記事の投稿 私は「Tableauの技術力を磨くための十の試練」の考え方について自身のブログに記事を作成しました。 具体的には、パフォーマンスを構成する要素についての記事や社内データ基盤の在り方について記事を作成しました。 この活動は正直他の誰の役にたったかは分かりませんが、インプットした内容をアプトプットする事で内容の整理ができました。 苦労したこと 苦労したことはタスク管理と時間の捻出です。 T・Sさんが初級の試験を着々と突破していく中で、頭からつまずいていました。 はなからそのつもりでのチャレンジではありましたが、想像以上に一つ一つの試験クリアに時間がかかってしまいました。 2022年10月の配属後は1ヶ月間各システムの説明を受けた後に、業務と課内技術研修(バッチや定義書の設計ワーク)を並行して行っていました。しかしその課内技術研修を完了させないままチャレンジを開始し、別途新規業務もいただいてパンク寸前でした。 終盤には上長のご協力で業務量を調整いただいたり、残業での学習時間の確保を許容いただき、なんとか合格する事が出来ました。 「これらの経験を経て、タスク管理について自分なりの方法を見いだす機会となりました。」 とはまだ言えないレベルなので引き続きこの問題と向き合っていきたいと思います。 学んだこと タスク管理やTableauのスキルに関してはもちろん学びがありましたが、その他について記載します。 私が学んだことは 文化醸成の重要性 です。 この資格勉強を通して、Tableauのスキルを叩き込まれました。しかし、Tableauの機能を熟知しているからと言って良いダッシュボードが作成できるわけではありません。 ダッシュボード作成はダッシュボードを作成する明確な目的を持ち、それを達成するためにどのようなデータを用いるか考える必要があります。 その為、直接的にビジネスに携わっていない言わばエンジニアサイドの私がこの力を発揮するには、ビジネスサイドの方々と共通認識を持ち、一緒にダッシュボードの作成を行う必要があります。 その方々の明確な目標とビジネス知識を正確に受け取り、ゴールへのサポートをするのが我々の役割です。 しかし、DataSaber認定後にユーザーのサポートを行った際にはサポートを円滑に行うことができませんでした。 何故かというとお互いの常識を理解していなかった為です。 私はビジネスサイドの理解が浅く、ユーザーはデータの理解が足りていませんでした。 複数の事業を持つ弊社にとって、全てのビジネスについてエンジニアサイドが理解する事はできませんし、他事業部のデータ活用の事例共有や分析用のデータ共通基盤を運用する事は、ビジネスサイドにはできません。 異なる役割の中で 両者が近い距離で、目標を共有し、足並みをそろえて働く事の大切さを学びました。 その為にはこの考え方についても共通認識を持つ必要があり、組織として文化を醸成する事が必要です。 その文化醸成こそが我々DataSaberに求められるものだと学びました。 今後のこと 現在社内に4名いるDataSaberを中心にデータについての考え方を発信して、文化を醸成していきたいです。 また、それに伴う様々な知識やスキルを積極的に会得していきたいです。 文化を醸成する手段がまだ明確ではありませんし、そこで活用するツールがTableauでなければならない訳ではありません。 様々な方法を模索して、一歩一歩着実にこの考えを広めていけたらと思います。 データが集まる会社でありそこにはたくさんの可能性があると思っています。 文化を醸成し、同じ方向を向いて、新たな価値創造に貢献できればと思います。 終わりに DATA SABERにチャレンジしたことを書いてみました。たくさん苦労したり、躓いたりしたのですが、頑張った結果DATA SABERになれたことは大変うれしく思っています。 ですが、2人とも、DATA SABERになれたことがゴールだとは思っていません。 社内に目を向けると、データドリブン文化を根付かせるという大きな目標が存在しています。また、データ活用人材を育成したり、データ活用を行っている人向けに情報発信したりなど、社外においてもDATA SABERとしての役目を果たさないといけません。 師匠は、私たちが社内外で精力的に活動できると期待して、DATA SABERに認定してくれたと認識しています。 その期待に応えられるよう、データ活用の中心的存在となって活動を行っていきたいと考えています。 投稿 Tableau DATA SABERにチャレンジした話 は マイナビエンジニアブログ に最初に表示されました。
はじめに マイナビ内でTableau DATA Saber認定制度に挑戦された3名に、師匠(前編)・弟子(後編)それぞれの立場で2作に分けて体験記を書いていただきました。 本記事では前編・師匠についてお届けします。 自己紹介 ご覧いただきありがとうございます。データソリューション統括部 データ活用推進2課のI・Rです。 この度マイナビのデータドリブン文化醸成の足がかりになればと、DATA Saber認定制度に挑戦し認定されました。また後進育成のため、私自身がDATA Saberで身につけた知識を伝え、弟子も育てることができました。 今回はDATA Saber認定制度のご紹介と、認定までの歩み、後進育成についてお話したいと思います。 データ利活用を進めたいが、勉強のとっかかりがつかめない。 自己流でBIツール(DATA Saber認定制度ではTableau)を利用しているが、技術力に自信がない。 データ利活用を推進するにあたり、周囲を巻き込む方法がわからない。 こういったお悩みをお持ちの方の参考になれば幸いです。 DATA Saber(データセイバー)とは? DATA Saberは、周囲にデータの重要性を説くデータ分析スキルとマインドを持った人材の育成を目標としたプログラムです。 主催はTableau社の元社員であるKTです。このプログラムは2015年に開始され、2023年6月現在1,300名以上のDATA Saberが育成されています。 DATA Saberは一般的な認定制度とは異なり、単にTableauの知識を持っているだけではなく、データドリブンの文化を浸透させるために必要な情熱や意志を伝えるためのコミュニケーションスキルを身につけることが重要です。 その証拠として、DATA Saberでは必ず師匠と弟子の関係でチャレンジを進めます。 師匠を見つけることも最初の試験となり、DATA Saberになった後に何を成し遂げたいのか、なぜなりたいのかなどを師匠に説得する必要があります。 DATA Saberの試験概要 このプログラムでは、以下の試練を3ヶ月でクリアする必要があります。 ・データ理解に必要な技術力を身につける(全10回の技術試験に満点で合格する) ・データドリブン文化を推進するためのコミュニケーションスキルを身につける(コミュニティ活動を行う) また、試験突破に必要な勉強時間は約100時間程度となっています。 詳細については公式ウェブサイトをご覧ください。 https://datasaber.world/ DATA Saberに認定されるまでの歩み 前述の通り、DATA Saberになるためには現在DATA Saberの方に師匠になっていただく必要があります。 師匠探し まず第一歩目としてTableau社の営業職の方ににDATA Saberになりたい旨をお伝えしました。するとTableau社主催のイベントにDATA Saberの方が講演されると伺い、すぐに参加しました。 講演された方は、Tableauの教育プログラムを自社内用にカスタマイズし、モチベーションとなるよう報酬体系を社内で調整し、BIツールが当たり前に使われる文化を浸透させるまでの軌跡を実体験を交えてお話してくださいました。マイナビにデータドリブン文化を浸透させる足がかりとしてDATA Saberになろうと考えていた私にとって、まさに理想の師匠像でした。 講演後にお話する機会があり、優れた実績を持つ方の弟子として迎え入れていただきたい旨をお伝えしたところ、快諾していただき、無事にDATA Saberのチャレンジが始まりました。 全試験突破までの勉強時間は120時間 試験突破までの苦労については、私の弟子が後編で取り上げていただく予定ですので、詳細には触れません。 Tableauは独学で身につけたため、知らない機能に驚くことはもちろんですが、同じデータでもグラフの作り方1つでより直感的に理解できることを体験しました。 師匠からのレクチャー会や、Twitterを通じてDATA Saberに挑戦中のメンバーとの勉強会、ディスカッションを経て、約2ヶ月半でDATA Saberに認定されました。 DATA Saberになって、なぜ弟子を育てたのか? DATA Saberになった後、すぐに弟子を取りました。その理由は大きく2つあります。 組織全体のデータリテラシーの底上げ データドリブンな文化を育成するためには、アイディアやノウハウ、気づきを組織内で共有する必要があると考えました。経験や知識を独占せず、他のメンバーと共有することで、個人だけでは気づけなかった洞察やアイディアが生まれるからです。 徐々に集合知を拡大することでデータリテラシーも向上し、組織が抱えるビジネス課題をデータを通じて正しく理解し、解決策を生み出せるようになっていくのではないかと考えています。 部門間の協力体制の構築 新しい文化の醸成は試行錯誤の連続です。1つの解決方法ですべての課題を解決する万能薬は存在せず、さまざまな施策を地道に試していく忍耐力が必要です。そしてこれらの施策には単一の部署ではなく、部門や職種を超えた協力関係が不可欠だと考えています。 DATA Saberでは師弟関係を築き、3ヶ月間で約100時間の密なコミュニケーションを取ります。ここでは、データの活用方法について深く話し合う機会も多くあります。この時間を通じて結束が生まれ、互いに協力し合える関係性を築くことができたと感じています。 今後の師匠としての未来像 ビジネスサイドの課題解決に貢献できるよう、課題の整理から関与し、共に取り組むことを考えています。エンジニア部門やビジネス部門といったセクショナリズムに陥ることなく、最終目標であるビジネス価値の創出に向けて、情報交換を行いながら課題解決を進めていきたいです。 そのための一歩として、データ利活用に興味を持つビジネス部門の方々にDATA Saberの活動についてお話をし、弟子として育成することでデータドリブン文化の醸成に貢献したいと考えています。 ビジネス部門の方々にデータの重要性やその有効活用方法について啓発を行い、共通の認識を持つことで、より効果的な課題解決とビジネス成果の向上を図ります。 またDATA Saberの数が増えた際には、定期的なワークショップや勉強会を通じて、ビジネス部門との連携を強化し、具体的なプロジェクトにおいても共同で取り組む機会を増やすことも考えています。さまざまな視点や専門知識を持つビジネス部門との連携は、より総合的な解決策の発見やイノベーションの創出に繋がると信じています。 これによって、データドリブンなアプローチが組織全体に浸透し、ビジネス課題に対する的確な洞察と戦略的な意思決定が行われるようになることを目指します。ビジネス部門との連携を通じて、より価値ある成果を創出し、組織の成長に寄与することが私の思い描く未来像です。 投稿 データドリブン文化の推進のためにTableau DATA Saberを取得し、弟子を育成した話 は マイナビエンジニアブログ に最初に表示されました。
はじめに この記事は2023年1月に、株式会社マイナビ デジタルテクノロジー戦略本部(以下「デジ戦」)内で定めた「コミュニケーションガイドライン」について、その背景を含めて紹介する記事です。 この記事のポイント コミュニケーションガイドラインとは、コミュニケーションを取るうえで守ってほしいこと、心がけてほしいことをまとめた資料 関心のある人に集まってもらいメンバーの声を聞きながらボトムアップ式に決めていった ガイドラインでは「オープンコミュニケーション」「アジリティの高さ」「目的意識」の3つを必要な心がけとして掲げている コミュニケーションガイドラインの効果については、半期に一度の定期的なアンケートをとることで測定する 背景 2019年末からのコロナ禍を経て、コミュニケーションの取り方は変わりました。 在宅ワークも一般化し、今までは当たり前のように顔と顔を突き合わせて会話していたものが、チャットやハドルミーティングなど、オンライン上での会話がメインになっていきました。 皆さんは、社内コミュニケーションがしやすくなったと感じますか? 今までよりコミュニケーションが取りやすくなったと感じる方、逆に取りにくくなったと感じる方、様々いらっしゃるのではないでしょうか。 このような感覚の差は、皆さんのコミュニケーションの「常識」が異なることで生まれています。 なかには、コミュニケーションが取りづらくなってしまったがゆえに、仕事の効率が落ちたと感じる人もいるでしょう。 日常のコミュニケーションのモヤモヤによって、仕事にマイナスの影響が出るなんて、とても勿体ないことですよね。 そこで、「デジ戦」内において コミュニケーションの取り方に対する目線を合わせる ため、「 コミュニケーションガイドライン 」というものを作成することにしました。 コミュニケーションガイドラインとは 我々が作成した「コミュニケーションガイドライン」とは、その名の通り コミュニケーションをとるために守ってほしいこと、心がけてほしいことをまとめた 資料です。 コミュニケーションガイドラインを通して「デジ戦」内の コミュニケーションを最適化し、従来の業務の生産性を向上したり、部署を越えたコラボレーションを強化していく ことを目指しています。 あくまで「ガイドライン」ですので、これに違反したからと言って罰則があるわけではありません。 ただ、全員が必ず一度は目を通し、できるだけこれに沿ってコミュニケーションを取っていただきたいという位置づけになっています。 ガイドラインの詳しい内容は後ほどご紹介しますが、ガイドラインは大きく「 コミュニケーションの手段の選び方 」と「 会議開催/参加時のルール 」の2軸からアプローチをしています。 コミュニケーションガイドラインの作り方 プロジェクトの進行は事務局で行いました。 ただし、コミュニケーションガイドラインの作成は「デジ戦」全体に推進メンバーの募集をかけ、 興味のあった人が集まりプロジェクトを企画、そしてプロジェクトメンバーの声を聞きながら民主的に進めていきました。 「デジ戦」はとても人数の多い事業部かつ「デジ戦」の中でもたくさんの部署に分かれています。 そうすると、既にそれぞれの部署における特有のコミュニケーション文化が醸成されております。 また、役職や仕事内容における感じ方の違いも当然あります。 できるだけ多くの人が使いやすいガイドラインにするため、実際に色々な部署の社員の方にヒアリングをし進めていきました。 集まったプロジェクトメンバーは全部で11人。部署も役職もバラバラです。 募集をかけてすぐに予想していたよりも多くメンバーが集まりましたので、急遽締め切りを早めました。 その集まり方から、 社員のコミュニケーションに関する関心(課題)の大きさ を感じました。 ガイドラインはまず事務局で素案を作成し、その後プロジェクトメンバーを3人から4人のグループに分けそれぞれ2回ずつ計8回のディスカッションで意見を出してもらい、それを参考に詰めていきました。 プロジェクトメンバーはコミュニケーションに関心の高いメンバーであるため、ディスカッションでは鋭い意見をたくさん聞くことができました。 おかげで、多くの人に使ってもらいやすいガイドラインになったのではと思います。 完成したコミュニケーションガイドラインの紹介 マイナビ「デジ戦」内コミュニケーションガイドラインの構成はこのようになっています。 ※第1版完成後から改定をしており、2023年4月時点の内容をご紹介します。 必要な心掛け コミュニケーション方法 シチュエーションごとのコミュニケーション方法 会議のルールとコツ ①会議目的ごとのルール ②会議のコツ Web会議のカメラに関して デジ戦内でのチャット利用についてのガイドライン ガイドラインの概要 はじめに、このコミュニケーションガイドラインの目的や適用範囲などを記載しています。 あくまで「ガイドライン」のため、強制力は持ちません。 また、適用範囲は「デジ戦」内としていますが、活用できそうであれば「デジ戦」外の部署や社外の方とやり取りする際にも利用いただくこともOKとしています。 必要な心掛け まずは、コミュニケーションをとるうえでの基本的な心掛けについて言及しています。 我々は「 オープンコミュニケーション 」「 アジリティの高さ 」「 目的意識 」の3つを必要な心がけとして掲げました。 これらを常に意識していれば、自然とコミュニケーションガイドラインに沿った行動をするようになるはずというものです。 コミュニケーション方法 我々はコミュニケーションの種類として「 チャット 」「 短い会話 」「 会議 」「 つぶやき・メモ 」の4つがあると整理しました。 それぞれの定義といつどのように使うのがよいか、ということを説明しています。 シチュエーションごとのコミュニケーション方法 続いて、もう少し直感的にコミュニケーション方法を使い分けられるように、図解しました。 ここでは「緊急度」と「重要度」の2軸で整理していますが「何を緊急(重要)とみなすか」については、個人や部署によって感覚が異なりますので、あえて具体的に示さず、現場に判断をゆだねる形としています。 会議のルールとコツ 会議はどうしても時間を拘束されてしまうため、なるべく減らしたいと考えていますが、どうしても必要な会議はあります。 その会議の時間をなるべく質の高いものにするため、会議のルールを定めました。 また、会議の目的に応じて守るべきルールは異なると考え、会議の目的別にルールを決めています。 ルールとは別に会議の「コツ」として、オフラインとオンラインが混在する会議の際に心がけてほしいことに言及しました。 また、アジェンダや議事メモの作成をルールとしておりますので、そのテンプレートも作成しました。 Web会議のカメラに関して Web会議の「顔出し」についてある程度決めがあった方がいいというご意見のもと「デジ戦」全体にアンケートを取った上で、カメラオンを「推奨」としました。 デジ戦内でのチャット利用についてのガイドライン コミュニケーション方法の中でも特に多く使われるようになった「チャット」について、 メンションの後に「様」をつける や 定型句としての「お疲れ様です」をつける などが人によってバラバラになってしまっていました。 こちらも余計な気遣いなくコミュニケーションをとれるように、ガイドラインを定めました。 コミュニケーションガイドラインの効果測定 コミュニケーションガイドラインを作成したうえで作りっぱなしにしてしまうと、せっかく作ったものの効果がわからずもったいないですし、その時々に合わせて改良を重ねてよりよいものにしていきたいという思いがあります。 コミュニケーションガイドラインの効果がどのくらいあったかについては、半期に一度の定期的なアンケートをとることで測定する予定です。 また、それとは別軸で、ガイドライン作成に協力してもらったプロジェクトメンバーに各部署における状況をウォッチしてもらい、実際の肌感レベルでの状況も聞いていければと考えています。 あとがき 今回のコミュニケーションガイドラインの作成については、「デジ戦」内でそういった取り決めを行うことがあまりなかったため、新鮮で挑戦的な取り組みだったと思います。 プロジェクトメンバーからの意見を通して、隣の部署でもかなり文化が違うことがわかりましたし、意外と社内のコミュニケーションについて課題を持っている人は多くいることが発見でした。 今回のコミュニケーションガイドラインが、少しでもマイナビ「デジ戦」内での働きやすさにつながればいいなと思います。 投稿 デジタルテクノロジー戦略本部のコミュニケーションガイドラインを作成しました!! は マイナビエンジニアブログ に最初に表示されました。
はじめに 皆さんこんにちは。 本日はクリスマスですね!私は幼い頃に両親からクリスマスプレゼントとして、『人生ゲーム』を買ってもらったことがあります。 そんなキッカケもあり、現在はボードゲームが趣味でして、当社のボードゲーム部にも所属しております。 マイナビのボードゲーム部では、業務後、不定期にボードゲーム会を開催して、みんなでワイワイやっています。 そして、閑話休題、今回、当社がお世話になっている某社のご厚意により、非売品の「情シスすごろく」というボードゲームをご提供いただきました。 実体験を基に作成された、リアルな情シスの雰囲気を味わえるボードゲームという事でしたので、早速遊んでみたレポートをお送りします! 「情シスすごろく」とは? 「情シスすごろく」は、転職してきたばかりの情シス社員として、企業の情報システム部門の 「あるある」 や トラブル を追体験できることをコンセプトとした、4人用のすごろくゲームです。 トラブルまみれの1か月にしっかり対応して乗り切り、より平穏に過ごしつつ、他者のサポートをより多くできた人が、”情シスの鑑(勝者)”となります。 遊び方 ルール 基本的には手番のプレイヤーがダイスを振ってコマを進める「すごろく」となります。 大きな違いとして、各プレイヤーは5ターン以内にゴールしなければいけません。 (1ターンを1週間とし、5週間(1か月間)乗り切る事に見立てられています。) 途中で止まったイベントタイルに応じてイベントが発生し、メンタルや体力が変化していくのですが、このメンタルの状態に応じて次のターンに振るダイスの種類が変わります。 ※メンタルがボロボロになるとサイコロの目の期待値が下がり、なかなか進めなくなってしまいますが、極限状態では"7"が出ることも!? 特定の条件を満たすことにより、イベントが発生した際に、他者に協力を仰ぐことができる「ユーザーコミュニティ」に所属することになります。協力したユーザーは協力に応じて「支援回数」を得ることができます。 最終的にゴールできた人( 1か月乗り切れた人 )の中で、より 平穏に過ごし (体力が多い)、 他者のサポートをより多く できた(支援回数が多い)人が ”情シスの鑑(勝者)” となります。 準備 各プレイヤーはそれぞれ個人ボードを初期値に設定する。 ■個人ボード プレイヤーの状態を管理するボードです。 ・ターン数 ・メンタル ・支援回数 ・体力 の4項目があり、ゲームで発生するイベントや行動によって変化していきます。 イベントタイルを裏面にしてすごろくのコースを作る。 ■イベントタイル マスに止まった際に発生するイベントが記載されています。 ・社員の端末からマルウェアが発見された ・従業員のIDとパスワードが漏洩した といったインシデントや ・古参エンジニアに相談したら、なぜか怒られた ・本部長に孫の〇witchの設定を頼まれた といったやるせないイベントなどが設定されており、回避するすべを持っていない場合はメンタルや体力にダメージを受けることになります…。 アイテムカードを各プレイヤーに7枚ずつ配る。 ■アイテムカード イベントを回避したり、メンタルなどを回復したりするために使用するアイテムとなります。 ・メール誤送信対策ツール ・多要素認証ソリューション といった、インシデントに対応できそうなソリューションや ・焼肉無料券 ・ビール といった、やるせなさを解消できる(?)アイテムなど、色々なものがあります。 イベントの中には「〇〇があれば回避可能」といった記載があるものがあり、該当するアイテムカードを使用することで回避できます。 また、ゲーム後半では、アイテムを捨てる事によってサイコロの出目にプラスしてコマを進めることができます。その際、そのアイテムが「必要ない理由」を宣言する必要があります。 これで準備完了です! ゲームの進め方 スタートプレイヤーから時計回りに1ターンずつ行い、全員が5ターンずつ実施します。 ターンは以下のように進行します。 ターン進行 個人ボードのターン数を進めます。 アイテムカード使用 使用できるアイテムカードがあれば、このタイミングで使用することができます。 サイコロ振って移動 自分のメンタルに合ったサイコロを振り、出たマス分進みます。 イベントの処理 止まったマスのイベントタイルを開き、イベントの処理を行います。イベントを回避できるアイテムカードがあれば、このタイミングで使用します。 全員が5ターン終わったタイミングで勝者判定を行います。 ゴールまで進めた人の中で、個人ボードの「体力」+「支援回数」の値が大きい人 が ”情シスの鑑(勝者)” となります。 やってみた はじまり 「もらった。やろうぜ」の課長からの一言で、今回の 「「情シスすごろく」で遊ぼうの会」 が企画されました。 そして翌日にはデジタルテクノロジー戦略本部全体に参加者募集の投稿が行われました。フットワークが軽い! 幸いなことに多くの方から参加の申込をいただき、無事、開催決定となりました。 ありがとうございます! 当日 とある日の業務後、会社の会議室で開催しました。 定時で業務を切り上げて会議室へ行くと、既に人が集まっており、みんなで軽い自己紹介を行った後、ゲームを始める事になりました。 ゲームには参加しないけど少しだけ見学を…という方にもちらほら来ていただいていて、そこから話の輪が広がる場面もあり、全体としてわちゃわちゃした雰囲気でした。 (私含め)みんな初めて行うゲームだったので、説明書を見ながらやんややんやと準備を行い、和気あいあいとゲームが進みました。 イベントタイルに止まり、 「突然、全社テレワーク環境の導入がトップダウンで降りてきた」 というイベントが発生した際には、 「あ~コロナ初期のあるあるですよねぇ…。」「ウチはコロナ以前から一部テレワークを導入してたから、他に比べたら多分マシだったと思いますけど…。」 といった、当社の情シスでの出来事を交えながら、リアルな経験を元にした会話が行われたり、 アイテムカードを捨てる際には そのアイテムが必要ではない理由 を宣言する必要があるのですが、 「ウチでは全部Excelで管理するので、プロジェクト管理ツールはいりません!!」 といった爆弾発言で周りから総ツッコミを受けたりと、終始なかなかの盛り上がりを見せていました。 1ゲーム30分程度で終わるため、メンバーを変えて複数回遊ぶことができましたが、色々なあるある話や当社情シスの話などが話され、初対面でも会話が弾んでいました。 感想 本質的にはすごろくなので、サイコロの出目次第のところが大きいのですが、そのおかげで初めての人でも楽しく遊ぶことができたと思います。 人によってアイテムカードを捨てて出目をブーストするタイミングや、捨てる際の言い訳に性格が出ていて、より深くその人を知ることができた気がします。 リアルに基づいたイベント(インシデント)に対して、「〇〇(ソリューション)があれば回避可能」といった回避策が記載されているので、 実際のソリューションに対する理解度 が上がり、ソリューションを導入していない時の リスク等について意識して学ぶ事ができた と思います。 楽しく学べて、情シスの雰囲気もなんとなくわかる良いボードゲームでした! おわりに 今回「「情シスすごろく」やってみた」という形で記事を書かせていただいたのですが、情シスすごろくに限らず、ボードゲームはプレイスタイルに個人の性格がとてもよく出ると思っています。 自分以外の方の考え方に触れられたり、初めましての方の"人となり"がなんとなくわかったり、普段一緒に業務している人の意外な一面が見れたりと、コミュニケーションツールとして非常に優秀だと改めて感じました。 特に今回の情シスすごろくは、システム系の業務をしている人たちで行った事もあり、イベントタイルのインシデントで一喜一憂したり、アイテムカードを捨てる理由の苦しさにみんなで笑ったりと、和気あいあいと親睦を深めることができました。 また、楽しんでいるうちに情シスについての理解が少し深まるといった学びも生まれたので、情シスなんもわからんって方にも是非遊んでいただきたいボードゲームでした。 以上、お読みいただきありがとうございました。 投稿 「情シスすごろく」をやってみた話 は マイナビエンジニアブログ に最初に表示されました。
はじめに 気付いたらもう12月ですね!あっという間の1年間でした… 最近は冷え込む日々が続いていますが、みなさま体調はいかがですか。 こちらの記事は今年4月に入社し、システム部署の中でも「 基幹システムや情報システムの管理、運用 」を行っている部署に配属された新卒4人で書いています。 ・文系出身でIT職に興味がある方 ・IT職でも開発以外の業務に興味がある方 上記に当てはまる方向けにマイナビの基幹/情報システムに関わる仕事についてまとめました。 「社内SEとは何か」から「社員の1日のスケジュール」など、基幹/情報システム担当ならではの話が盛り沢山なので最後まで読んでいただけたら嬉しいです! 一般的に社内SEとは? 社内SEとは 社内のシステムを管理したり、 システム関連で社内で発生した依頼や問題を解決していくお仕事 です。 お客さんとなるのは弊社の社員、営業や経理など非システム職の人が大半です。 社内の人たちが使用するシステムに不具合がでたり、改良してほしいという依頼が出たときに私たちの出番がやってきます。 社内でマイナビすべてのシステムを開発しているわけではないので、ベンダーというシステムを開発してくれる方たちに改修依頼をすることが多いです。 そのため、お客様という意味では弊社内の人ですが、一緒に仕事をするパートナーとしてはベンダーの人も挙げられます。 「お客様(社内の人)の要望を汲み取って、ベンダーの方たちに伝える」というのは非常に重要な業務の一つです。 基盤を支える「 縁の下の力持ち 」であり、立場の違う人をつなぐ「 架け橋 」の役割を担っているのが私たちの仕事です。 新卒4人にインタビュー 配属されてから2か月。新卒の私たちが普段どんな業務をしているのか、業務をしていて感じたことなどを赤裸々に答えました! ■M.Hさん(基幹システム担当) (1)現在どのような業務を行っていますか? 「社内会計システムの保守・運用」を担当しています。システムにエラーがでていないかメールでチェックをしたり、案件のリリース準備のため、関係者に連絡を取る仕事を任せてもらっています。 また、週に1回ある会議の進行や議事録作成も行っています。 直近ではプロジェクトのテスト仕様書の作成やレビューの一部をお手伝いさせていただきました。 (2)どんな人が基幹系部署に向いていると思いますか? 報連相がしっかりできて、状況把握が得意な人が向いていると思います。扱うシステムが多いわりに人が少ない少数精鋭な部署です。 なので、周りの人の仕事量を察して気遣いができる人や、無駄が発生しないよう効率化を意識することが得意である人、連携や確認を面倒くさがることなく行うことができる人が向いているのかなと感じています。 ■Y.Nさん(基幹システム担当) (1)現在どのような業務を行っていますか? H.Mさんと基本的には同様の業務をしています。 その他に、経理からの質問対応や、申請書類の作成などもしています。 (2)配属前に抱いていた基幹系部署のイメージを教えてください。またイメージとのギャップはありましたか? ミスが許されないという意味で緊張する部署というイメージが強くありました。 なぜなら研修で基幹系システムは「会社の業務と直接関わるシステム」であり、 基幹システムが停止した場合は、会社全体に影響するので会社への影響度が大きいと伺っていたからです。そのため、自信がある人でないと難しい部署だと考えていました。 安定稼働するのが当たり前のシステムである以上、ミスが許されないという部署イメージは変わっていません。 しかし、配属後ミスが許されないからこそ何事も自信を持っている人よりも心配になってきちんと確認できる人の方が多いというイメージに変わりました。 私たちの部署は、複数人で業務の確認をするなど心配性な人こそ安心できる場所であると現在は考えています。 ■Y.Sさん(情報システム担当) (1)現在どのような業務を行っていますか 「全社向け会計システム」と「システム職向けナレッジ共有ツール」を担当しています。 前者は全社向けということもあり非常に大きなサービスです。ひよっこの私が一朝一夕で管理できるシステムではないので、まずはシステムの使用フローや内部的な機能について学んでいるところです。 後者はアカウント発行依頼の対応や運用改善を行っています。運用改善では、アカウント発行の流れで余分にかかっている手間を省いたり、ユーザーがより記事を共有しやすくするための統制を考えています。 問い合わせ対応はどちらも共通して担当しており、サービスを利用している社員の方々の「困った」や「こんな使い方がしたい」といった問い合わせを調査/検証し、返答しています。 (2)配属前に抱いていた基幹系部署のイメージを教えてください。またイメージとのギャップはありましたか? イメージとの相違あり/なしでお答えします! イメージと相違なかったのは業務内容です。SEという職種ではあるものの、コーディングはほとんど行いません。私の場合は皆無です。 メインで行う業務はベンダーさんと社内ユーザーの間を取り持つこと。実際にお話ししている際中に認識齟齬を解決することもあれば、会議のアーカイブを見直して一つずつ取り決めを確認することもあります。 逆にイメージとギャップがあったのは先輩社員の方々の人柄です。 配属前は固い雰囲気なのかなと思っていたのですが、お話好きな方が多いのが少し驚きでした。仕事上で同期との絡みがないので、一人で黙々と作業するのかな…と震えていましたが、課の先輩、上司の方との雑談も交えながら楽しく仕事ができています。 お話しする機会が多いと、業務上で分からないことや困ったことがあったときに相談しやすいのでとてもありがたいです…! ■R.Tさん(情報システム担当) (1)現在どのような業務を行っていますか 「Webデータベースソフト」と「マイナビグループ社員の情報を一元管理するID管理システム」を担当しています。 ユーザー(社員)からの問い合わせ対応では、システムの仕様をマニュアルで確認したり、実際に動かしてみて、手探りですが自分も学びながら対応しています。 一方で異動に伴う社員や組織の情報の更新や休退職対応や復職対応など、かなり人事に近い業務も行っています。 (2)業務を行う上で意識していること・気を付けていることはありますか? 1番意識していることは「自分の判断だけで進めない事」です。 私が担当しているシステムは人の情報を扱っているのできっとこうだろうという判断で 間違った情報を取り込んでしまったり、データベースを壊してしまうようなことがあれば 社員の業務に直接影響が出てしまいます。 そのため今は少しでも不安なことがあったら先輩に質問を確認をしています。 ただ自分から先輩に確認しに行くなどの積極性は忘れないようにしたいです! いかがだったでしょうか。 担当するシステムや業務の内容は異なりますが、基幹/情報システムというマイナビの中枢を担うシステムの担当として、4人とも強い責任感を感じながら業務をしていることがわかりました。 先輩へのインタビューと1日のスケジュール これまでは、一般的な社内SEの仕事内容や、新人目線で思ったことや気付いたことについてまとめました。 「コーディングをしないシステム職」の業務についてなんとなくイメージできましたでしょうか? 次は基幹/情報システム担当として経験を積んだ先輩方、課長・部長にご協力いただき、1日のスケジュールや業務の中で大切にしていることなどを伺いました。 先輩社員インタビュー ■N.Tさん(基幹システム担当) 債権管理システムの保守・運用を行う 1日のスケジュール 時刻 作業 コメント 9:05 出社(在宅の場合はPC起動) 9:15 業務開始 基本的には前営業日の残作業や、メールチェックから入ります。対応が必要な事象が発生している場合は、そちらの確認を優先して実施します。 10:00~11:00 改修プログラムの検証環境リリースのために必要な書類の確認 11:00~12:00 昼の予定に合わせて早めのお昼休憩 12:00~14:30 サーバーの月例メンテナンス作業を実施 日中に停止させるので時間厳守で行っています。 15:00~16:00 週次のプロジェクト進捗報告会議と隔週での保守案件の進捗確認会議 プロジェクトごとに先週に実施した案件の説明と、来週にかけて実施する予定の報告をします。また、この日は隔週で実施している「不具合管理システムでのチケットごとの確認」を実施しました。 16:00~17:45 タスク整理と対応 10時からの会議内で話題に上がった内容などについてアクションが必要なものから対応していきます。 マイナビで働いていて思うこと スキルを得るための環境が整備されてきており、非常にありがたい点だと感じています。 会社経費での外部研修を積極的に受けるように推奨されており、自部署では業務へプラスになりそうな分野(直接、間接問わず)について、業務時間内で勉強時間を確保するよう求められています。 K.Sさん(情報システム担当) 全社員が利用するメールツールの管理及びMicrosoft製品全般の管理・導入 1日のスケジュール 時刻 作業 コメント 08:50~09:15 出社 早めに来て優雅な時間を過ごすタイプです。 09:15 業務開始 09:15~11:00 メール確認/スケジュール確認/定例作業 まず私はメール確認とその日のスケジュールを確認します。その後、定例作業(導入しているサービスの定期的なメンテナンスやお問い合わせの対応)を実施します。 12:00~13:00 会議 社内のコミュニケーションについての会議に参加しました。 13:00~15:00 会議 Microsoft製品についての会議に参加しました。 15:00~16:00 会議 実行中案件についての会議を行いました。 17:00~17:45 定例作業 終業前にメール確認・返信と、従業員の方から受けた導入しているサービスについての設定依頼を確認し対応します。 18:00 退社 ※インタビュアーコメント: 12:00~13:00の会議は別部署での企画会議です。 マイナビでは企画策定や開発作業に参加するための公募が多くあり、興味さえあれば参加することができます! マイナビで働いていて思うこと 私は中途でマイナビに入社しましたが、前職と比べて「休暇が取得しやすい」という点が良いところかなと感じています。 社員の方の中には毎週1日午前休を取得している方や、最近では男性で育児休暇を取得されている方もいます。 上長から有給取得を促される風潮があり、比較的休暇は取得しやすい環境かな思います。 基幹/情報システム担当として大切にしていること 私たちが所属するコーポレートIT統括部ではITを通じて社員の働きやすさや、生産性を向上していくことをミッションにしています。 ■新入社員の気づき 配属されてから一番感じた大切なことは システムの利用者に寄り添うこと です。 これはシステム利用者の言う通りにすると言う意味ではなく、相手の業務内容を知り、 利用者にとってのベストを模索する ということです。 それを実現するために必要な作業は、まずユーザーがどのように担当システムを利用しているのか熟知することです。 例えば、ユーザー(社員)の業務を考えながら担当システムの動作確認をしたり、 ユーザーの普段の業務をヒアリングしたりしています。 ■部長・課長に聞きました 我らが部長・課長に「基幹/情報システム担当として大切にしていることはありますか?」と質問したところ快くお答えいただきました(ありがとうございます…!) 大切にされていることはそれぞれたくさんあったのですが、その中から3つをピックアップさせていただきました! 1.安定稼働 「ユーザの本来の業務に対してシステムを意識させないほどの安定稼働」が第一です。 動いていて当然とされているシステムたちなので、安定稼働していないと全体的に支障がでます。 ここをいかに担保するかが重要になってきます。 2.現場社員の立場に立って考える システム導入や改修の際に、現場社員が実際の利用の流れを想像できるようにお手伝いするのが 私たちの仕事です。 なるべく画面キャプチャを多く使った資料を作ったり、とりあえず完成品に近いサンプル品を触ってもらうなどして業務が具体的にどうなるのかというのを意識してもらうように心がけています。 3.リスク共有 リスクを予想し未然に防ぐことと、問題が発生してから対処することでは、影響範囲も対応コストも全く変わってきます。 取り返しのつかない問題を発生させないためにも、リスクの予想/共有/対応策の検討は常に行っています。 そのため、ユーザー(社員)に対して事前にリスクを説明しプロジェクトを進めています。 「作業着手が遅れないように〇月〇日までに回答してもらう必要がある」 「数ある要望の中から取捨選択しないと予算オーバーとなってしまう」 「この要望を反映させると○○の処理時間が長くなる可能性がある」 など、具体的に伝えています。 あとがき 最後まで読んでいただきありがとうございました! システム職=プログラマーのようにコーディングをする人、というイメージを持っている方に 私たちのように社内のシステムを管理・運用する仕事もあるんだということを知っていただきたく、今回アドベントカレンダー企画に参加させていただきました。 またこの記事を読んで 「基幹/情報システム担当に興味がある!」 「性格的に結構向いているかも?」 と思ってくださった方が1人でもいらっしゃったら嬉しいです。 最後までお読みいただきありがとうございました! 投稿 コーディングしないシステム職がいるってほんとですか!?~社内SEのお仕事紹介します~ は マイナビエンジニアブログ に最初に表示されました。
はじめに 唐突ですが VSCode の拡張機能作ってみたくありませんか? 私は日々のコーディングの業務ではもちろん VSCode を使っていますが、痒いところに手が届かないといいますか、自分の思い通りのコードエディタにするために、あと一歩足りない・・・この機能があれば・・・と思うことがあったりします。 みなさんもこう感じた経験ないですか? こういったニッチな要望に答えてくれる拡張機能があればいいですが、なければ自分で作るしかありません。 ということで今回は VSCode の拡張機能の作り方をこの記事で紹介したいと思います! とりあえず Hello World してみる デバッグで動かしてみる VSCode の公式ドキュメント の Get Started を見てみるとサンプルの拡張機能(拡張機能の雛形)を作る方法が載っています。 この手順に従ってサンプルの拡張機能を作ってみます。 以下のコマンドを打って必要なモジュールをインストールして雛形を作ってみます。 npm install -g yo generator-code yo code 雛形は yo コマンドが対話的に作成してくれます。 今回は TypeScript を使って雛形をつくることとして、名前は適当に HelloWorld とします。 # ? What type of extension do you want to create? > New Extension (TypeScript) # ? What's the name of your extension? HelloWorld # ? What's the identifier of your extension? hellowold # そのまま Enter # ? What's the description of your extension? Sample extension # ? Initialize a git repository? n # リポジトリとしたい場合は Y を選択 # ? Bundle the source code with webpack? N # ? Which package manager to use? npm # お好みのものを選んでください # ? Do you want to open the new folder with Visual Studio Code? > Open with `code` これで、HelloWorld 拡張機能の雛形が作られました。 このまま F5 を押して拡張機能をデバッグモードで起動させてみます。 HelloWorld 拡張機能が有効になったデバッグ用の VSCode のウインドウが開きます。 この状態で、 Ctrl + Shift + p を押して、コマンドパレットを表示させ、 Hello World と入力するとコマンドがでてきます。 コマンドを実行してみると、右下のテキストボックスに Hello World from HelloWorld が表示されました。 コードを見てみる 拡張機能のエントリポイントは、src/extension.ts 内の activate 関数になります。 中身は です。(実際のコードではコメントが丁寧に入っています。) ▼helloworld/src/extension.ts import * as vscode from 'vscode'; export function activate(context: vscode.ExtensionContext) { console.log('Congratulations, your extension "helloworld" is now active!'); let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => { vscode.window.showInformationMessage('Hello World from HelloWorld!'); }); context.subscriptions.push(disposable); } export function deactivate() {} コードの中盤あたり の disposable オブジェクトが Hello World を表示させているコマンドの実態です。 let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => { vscode.window.showInformationMessage('Hello World from HelloWorld!'); }); ここでは、 vscode.window.showInformationMessage 関数を呼び出すコマンドを作成して、そのコマンドの ID を helloworld.helloWorld としています。( showInformationMessage はVSCode の右下部分にメッセージを表示させるメソッドです) ここで、サンプルの拡張機能で Hello World を表示させたときのことを思い出してみます。 右下に Hello World が出るのはコマンドパレットに Hello World を入力し、コマンドを実行したときでした。 このようにコマンドパレットから実行可能なコマンドにしている部分の記述が実は package.json に記載されています。 package.json の16-23行目に該当の記述があります。 ▼helloworld/package.json(一部抜粋) "contributes": { "commands": [ { "command": "helloworld.helloWorld", "title": "Hello World" } ] }, この部分で、コマンドのタイトルを Hello World とし、 helloworld.helloWorld をこの拡張機能が提供するコマンドとして登録しています。 このようにして、VSCode の拡張機能では package.json とソースコードに所望の処理を記述して、拡張機能を作っていくことになります。 パッケージ化 してみる サンプルの拡張機能の中身を理解できたところで、次はこれを実際に使える形でパッケージ化 してみます。 パッケージ化するところについては の記事がよくまとまっているので参考にします。 ( https://dev.classmethod.jp/articles/easy-vs-code-extension-development/ ) ※ 今回の記事では拡張機能を公開する部分についてはやったことがないので触れません。 パッケージ化するためには vsce コマンドを使うようです。 とりあえずインストールしておきます。 npm install -g vsce 正しくパッケージ化するために、まずは README を編集します。 ここを編集しないと vsce コマンドを実行したときに以下のエラーが発生してパッケージ化できません(2敗) ERROR Make sure to edit the README.md file before you package or publish your extension. # helloworld README sample extension README を直したら vsce コマンドを実行して拡張機能をパッケージ化します。 npx vsce package 場合によっては警告がでるので、適切に対応します。 WARNING A 'repository' field is missing from the 'package.json' manifest file. Do you want to continue? [y/N] y # git リポジトリにしてない場合に発生します WARNING LICENSE.md, LICENSE.txt or LICENSE not found Do you want to continue? [y/N] y 完了すると、 {拡張機能名}-{バージョン}.vsix ファイルが出来上がりました。(ちなみにバージョン名や拡張機能名は package.json で管理されています。) これでパッケージ化は完了です 実際にインストールするときは Ctrl + Shift + x で拡張機能のビューを表示させ VSIX からのインストール を選択し VSCode にインストールします。 おすすめのやり方について話してみる VSCode の API リファレンス を見ると様々な API の使い方が載っているわけですが、API の呼び出し方を説明するのみで、その機能を使うことで見た目がどう変わるのか、内部で何が起こっているのかをイメージすることは正直厳しいと思います。 例えば、エクスプローラーのようなツリー型のビュー( みたいなやつ)を作りたい場合に、膨大な使い方から作り方を探すのは大変だと思います。 そんなときは、VSCode の公式が公開している サンプル集 をみて、動くものから学んでいくのがおすすめです。 ここでは、よく使いがちな機能のサンプルをまとめており、クローンしてきて実際に動かしてみることで中で何が起こっているのか、見た目にどう影響するのかを確認してみることができます。( vim エディタ:memo:を作ってみる ってのもあったりします ) 実際に動かしてみて、中身を確認したあと API リファレンス を見ることで理解がしやすくなるんじゃないかと思います。(実際私はそうやって拡張機能の開発をしてます) また、VSCode の UI 構造やロジック部分の記述に慣れてくると、 dockerの拡張機能 や gitlens といった有名な拡張機能のソースコードから、所望の処理の部分を参考にして実装してみるのもいいと思います。 サンプル拡張機能に機能を追加してみる 最後に、紹介したおすすめのやり方でサンプルの拡張機能に の機能を追加してみます。 VSCode の下部ステータスバーに文字を表示させる 文字情報は VSCode の設定画面から指定する ステータスバーに文字を出す部分について調べてみる ステータスバーに文字を追加している拡張機能をサンプルのリポジトリから探してみます。 のコード内、 StatusBar クラスの vscode.StatusBarItem が該当の部分っぽそうです。 https://github.com/microsoft/vscode-extension-samples/blob/main/vim-sample/src/extension.ts ▼vim-sample/src/extension.ts class StatusBar { private _actual: vscode.StatusBarItem; private _lastText: string; constructor() { this._actual = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); this._actual.show(); } public setText(text: string): void { if (this._lastText === text) { return; } this._lastText = text; this._actual.text = this._lastText; } } 文字を表示させるには vscode.StatusBarItem オブジェクトを作る必要があり、それは vscode.window.createStatusBarItem 関数で、できるようです。 表示させる文字はどのように設定するのかも見てみます。 同じクラスの setText メソッド内のコードを見ると、 vscode.StatusBarItem オブジェクトの text プロパティに表示する文字を入れているみたいです。 API リファレンスも見てみます。 createStatusBarItem 関数は このリンク をちょっとスクロールした部分に定義がありました。 StatusBarItem クラスについてはこちらの リンク に使い方があるみたいです。 text プロパティを見てみると、どうやら特殊な書き方でアイコンも表示させることができることもわかりました。 設定画面から文字を取得する部分について調べてみる 次に設定画面から文字を得る部分を調べてみます。 このコード の あたりが設定から値を持ってきているところみたいです。 ▼codelens-sample/src/CodelensProvider.ts if (vscode.workspace.getConfiguration("codelens-sample").get("enableCodeLens", true)) { getConfigration 関数の リファレンス も見てみると、 WorkspaceConfiguration クラスのインスタンスを返していることがわかり、 その部分のリファレンス も見てみると get メソッドの使い方も分かってきました。 次に configration とは何かについても調べてみます。 リファレンス を探してみると、package.json に記述する設定みたいです。 参考にした拡張機能の pakcage.json を見ると configration の記述があることも確認できます。 ▼codelens-sample/package.json "configuration": { "properties": { "codelens-sample.enableCodeLens": { "type": "boolean", "default": true } } } 実装してみる これで機能追加する上で必要な情報が出揃ったので、実際に機能追加してみます。 今回は statusBarText という設定を追加してみて、ここの値をステータスバーに出すことにします。(デフォルトの値として default という文字を入れておきます。) また、文字の表示はウインドウが立ち上がったときにしたいので、 activationEvents に onStartupFinished を追加しています。 ▼helloworld/package.json(一部抜粋) "activationEvents": [ "onCommand:helloworld.helloWorld", "onStartupFinished" // 追加部分(拡張機能が有効化されたときに active 関数を実行する) ], ... "contributes": { "commands": [ { "command": "helloworld.helloWorld", "title": "Hello World" } ], // 追加部分 "configuration": [ { "type": "object", "title": "helloworld", "properties": { "helloworld.statusBarText": { "type": "string", "default": "dafault", "scope": "resource", "description": "ステータスバーに表示する文字を設定します" } } } ] } extension.ts にはサンプルのコードを見て学んだ API の使い方を参考に、以下を行うコードを追記します。 ステータスバーを作る 文字を設定から読み込む ステータスバーの文字として設定する ▼helloworld/src/extension.ts import * as vscode from 'vscode'; export function activate(context: vscode.ExtensionContext) { console.log('Congratulations, your extension "helloworld" is now active!'); let disposable = vscode.commands.registerCommand('helloworld.helloWorld', () => { vscode.window.showInformationMessage('Hello World from HelloWorld!'); }); context.subscriptions.push(disposable); // 追加部分 const statusBarItem = vscode.window.createStatusBarItem(); statusBarItem.text = vscode.workspace .getConfiguration('helloworld') .get('statusBarText', ''); statusBarItem.show(); } export function deactivate() {} それではデバッグモードで実行してみます。 値が表示されています 起動したばっかりでは、設定画面で値を指定していないのでデフォルトの文字が表示されています。 思った通りの動作をするか見てみる 次に設定ファイルに値を記入して、表示する文字を変更してみます。 Ctrl + , を入力して設定画面を出して、検索ボックスに helloworld と入力します。 のように設定が出てくるので適当な文字を入れてみます。 この際どうせならアイコンも表示させてみます。( アイコンの一覧 ) 文字が表示されるのは拡張機能が読み込まれたときなので、再読み込みさせます。 デバッグコンソールを表示している方の VSCode ウインドウから更新ボタンを押して再度デバッグを実行してみます。 下の文字が変更されました! アイコンもうまく表示できているみたいです! おわりに 今回は VSCode の拡張機能の作り方と、実際に作るときに参考にしたら良いドキュメントやサンプルコードを紹介しました。 これだけ多くのことができて、自由度が高いところが VSCode が使いやすいソースコードエディタとして知られている理由なんだと思います。 日々の業務で感じている僅かな苛立ちを、自分で拡張機能を作ってみて解決してみてはいかがでしょうか。 投稿 VSCode の拡張機能を作ってみる は マイナビエンジニアブログ に最初に表示されました。
副題: AWSのおかげでグリーンカレーが作れなくなった話 はじめに ※本記事は、AWS Organizations + CloudFormation StackSetsで複数AWSアカウントへのリソース展開を管理している方向けの内容になっています。 昨年、 マイナビ Advent Calendar 2021 にて、 こんな記事 を書かせていただきました。 要約すると、 CloudFormation StackSetsで組織やOUに展開しているCFnスタックについて、 そのデプロイステータスを通知するようにしたかったので、 グリーンカレーを作るついでに強引にデプロイステータスを確認するサーバーレスアプリケーションを作った。 という内容でした。 当時、StackSetsの各スタックインスタンスのイベントを、StackSetsやOrganizationsの管理アカウント側で検知する手段が無かったため、Step Functionsを使って 定期的にステータス変更をポーリングする ことで解決したわけです。 が、 それから約1年の時を経て、2022年11月にAWSから こんなアナウンス が。 Build event-driven applications with AWS CloudFormation StackSets event notifications in Amazon EventBridge 本日より、AWS CloudFormation StackSets で、Amazon EventBridge を介したイベント通知の提供が開始されました。イベント駆動型のアクションは、CloudFormation のスタックセットを作成、更新、削除した後に、トリガーすることができます。これを、CloudFormation スタックセットのデプロイで、CloudFormation API を介して定期的に変更をポーリングするカスタムのソリューションを開発または維持しなくても実行できます。 ( ゚д゚) (つд⊂)ゴシゴシ 定期的に変更をポーリングするカスタムのソリューションを開発または維持しなくても実行できます。 (;゚д゚) (つд⊂)ゴシゴシ _, ._ (;゚ Д゚) …!? つ、ついに待望の機能が実装されました!!!!! というわけで、とにかくイベント検知ができるようになった以上それを活かさない手はないだろうと、新しく各スタックインスタンスのデプロイステータスを検知する基盤を作り直しました。 本題 通知したいのは、「各スタックインスタンスのデプロイステータスの変更」です。 構成は別に図にするまでもないんですが、一応こちらの青背景部分になります。 SAM実装部分だけ見るとだいぶスッキリしました。 Slack通知をするだけなら、Chatbotを使ったりEventBridgeのトランスフォーマーでSlackAPIを叩いたりすればLambdaを書かなくても良いんですが、 Chatbotの通知内容だと情報が少なすぎる 参考: [アップデート] CloudFormation StackSets が EventBridge を介してイベント通知できるようになりました | DevelopersIO 条件分岐で通知内容をカスタマイズしたい といったことから、Lambdaを通してWebhookでSlackに投げる形にしています。 ついでに、アカウントIDだけでなくアカウント名も通知結果に含めるため、OrganizationsのAPIを叩いています。 また、StackSetsの管理自体は専用のアカウント(StackSets Account)に委任して行っていますが、その場合でもサービスマネージド型のStackSetsのイベントは Organizationsの管理アカウントで検知される ので注意。 実装 SAMテンプレート 何の変哲もない、EventBridgeルールとLambda関数を定義しているテンプレートです。 EventBridgeで拾うイベントタイプは CloudFormation StackSet StackInstance Status Change 、ステータスコードは 公式リファレンス を見てとりあえずオペレーションの失敗・成功を拾うために SUCCEEDED / FAILED / CANCELLED の3つとしています。 ▼template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: | Service-Managed StackSets' Stack Instance Status Notification to Slack(webhook) #-----------------------------------------------------------------------------------# Parameters: #-----------------------------------------------------------------------------------# SystemName: Type: String Description: input System Name. Default: stacksets-status-notify Env: Type: String Description: input Env Name. AllowedValues: - dev - stage - prod SlackWebhookUrl: Type: String Description: input Slack Incoming Webhook URL #-----------------------------------------------------------------------------------# Conditions: #-----------------------------------------------------------------------------------# isProd: !Equals [ !Ref Env, "prod" ] #-----------------------------------------------------------------------------------# Resources: #-----------------------------------------------------------------------------------# #---------------------------------------------------------------------------------# # EventBridge Rule #---------------------------------------------------------------------------------# StackInstancesStatusChangeEventRule: Type: AWS::Events::Rule Properties: EventPattern: source: - aws.cloudformation detail-type: - CloudFormation StackSet StackInstance Status Change detail: status-details: detailed-status: - SUCCEEDED - FAILED - CANCELLED Targets: - Id: !Ref NotifyFunction Arn: !GetAtt NotifyFunction.Arn #---------------------------------------------------------------------------------# # Notify Function #---------------------------------------------------------------------------------# NotifyFunction: Type: AWS::Serverless::Function Properties: Description: !Sub - Stack ${AWS::StackName} Function ${ResourceName} - ResourceName: NotifyFunction FunctionName: !Sub ${SystemName}-${Env}-NotifyFunc CodeUri: notify_function Handler: app.lambda_handler Runtime: python3.9 MemorySize: 128 Timeout: 30 Role: !GetAtt NotifyFunctionExecRole.Arn Environment: Variables: SLACK_WEBHOOK_URL: !Ref SlackWebhookUrl IS_PROD: !If [isProd, true, false] NotifyFunctionExecRole: Type: AWS::IAM::Role Properties: RoleName: !Sub ${SystemName}-${Env}-NotifyFunc-Role ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: NotifyFunctionExecRolePolicy PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowDescribeAccountName Action: - organizations:DescribeAccount Resource: '*' Effect: Allow AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com FunctionLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Retain UpdateReplacePolicy: Retain Properties: LogGroupName: !Sub /aws/lambda/${NotifyFunction} RetentionInDays: 30 StackInstancesStatusChangeEventRuleToNotifyFunctionPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt NotifyFunction.Arn Principal: !Sub events.${AWS::URLSuffix} SourceArn: !GetAtt StackInstancesStatusChangeEventRule.Arn 余談ですが、今回のtemplate.yaml作成にあたっては先日プレビュー版が出た Application Composer を使ってみました。 ただ、 うっかり余計なLambda関数作っちゃってから消してもフォルダは消えてない デフォルトのNode.jsからPythonに切り替えてもindex.jsとpackage.jsonが消えてない handler.handlerをapp.handlerに書き換えてもディレクトリ名は変わらない ポリシーが直書きのみで、IAMのマネージドポリシーを当てる手段が無い そもそもParameterつけられない 、、、と、まだ色々と粗く、結局大半はyamlを直接編集しました。 Windowsじゃなかったらまた違うのかもしれませんが… 今後に期待したいです。 Lambda イベントを受け取って、OrganizationsのAPIで対象アカウント名取得して、整形してSlackに投げてるだけです。 ▼notify_function/app.p import json import os import re from datetime import datetime # noqa: F401 from logging import getLogger, basicConfig, INFO, DEBUG import boto3 import requests # Logger Settings logger = getLogger(__name__) log_level = INFO if is_prod else DEBUG basicConfig(level=log_level) logger.setLevel(log_level) def get_account_name(account_id): """! Get Account Name AWSアカウントIDからアカウント名を取得する @param account_id(str) @return AWS Account Name.(str) """ logger.debug('start func: get_account_name') logger.debug('input: {}'.format(account_id)) if not account_id: return '' client = boto3.client('organizations') res = client.describe_account(AccountId=account_id) account_name = res['Account']['Name'] logger.debug('return {}'.format(account_name)) return account_name def generate_slack_data(data): """! Generate Slack Post Data SlackのWebhookに投げるPOSTデータを生成する。 @param data input event data. @return Slack Post Data.(dict) """ logger.debug('start func: generate_slack_data') logger.debug(data['detail']) stacksets_url = 'https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacksets?permissions=service' # noqa: E501 # Stack Instance account, region stack_instance_stack_arn = data['detail'].get('stack-id', '') arn_pattern = r'^arn:aws:.*?:(.+?):(.+?):(stackset|stack)/?(.*)$' stack_instance_region = re.sub( arn_pattern, '\\1', stack_instance_stack_arn ) stack_instance_account_id = re.sub( arn_pattern, '\\2', stack_instance_stack_arn ) stack_instance_account_name = get_account_name( stack_instance_account_id ) # Stack Instance status stack_instance_status = data['detail']['status-details']['detailed-status'] # StackSet stack_set_name = re.sub( arn_pattern, '\\4', data['detail']['stack-set-arn'] ).split(':')[0] # emoji if stack_instance_status == 'SUCCEEDED': color = '#2EB886' emoji = ':white_check_mark:' else: color = '#A30100' emoji = ':rotating_light:' slack_data = { 'attachments': [ { 'color': color, 'blocks': [ { 'type': 'section', 'text': { 'type': 'mrkdwn', 'text': '{} *<{}|StackSets StackInstance Status>*'.format( # noqa:E501 emoji, stacksets_url ) } }, { 'type': 'section', 'fields': [ { 'type': 'mrkdwn', 'text': '*Account*\n{}\n`{}`'.format( stack_instance_account_id, stack_instance_account_name ) }, { 'type': 'mrkdwn', 'text': '*Region*\n{}'.format( stack_instance_region ) }, { 'type': 'mrkdwn', 'text': '*StackSet*\n{}'.format( stack_set_name ) }, { 'type': 'mrkdwn', 'text': '*Status*\n{}'.format( stack_instance_status ) }, ] } ] } ] } logger.debug('return {}'.format(slack_data)) return slack_data def post_to_slack(slack_webhook_url, slack_data): """! exec HTTP POST request to Slack Incoming Webhook. Slack Incoming WebhookへデータをPOSTする。 @param slack_webhook_url @param slack_data @return Slack Post Result.(bool) """ logger.debug('start func: post_to_slack') headers = { 'Content-Type': 'application/json' } try: res = requests.post( slack_webhook_url, headers=headers, data=json.dumps(slack_data) ) except requests.exceptions.RequestException as e: err_str = str(e).replace(slack_webhook_url, '****') logger.error('[Error posting to slack] {0}'.format(err_str), stack_info=True) # noqa:E501 return False else: logger.info('Slack Post OK.') return True def lambda_handler(event, context): """! lambda handler Lambdaイベントハンドラ。 @param event input Event by EventBridge. """ logger.info('input event: {}'.format(event)) slack_webhook_url = os.environ.get('SLACK_WEBHOOK_URL') if slack_webhook_url: slack_data = generate_slack_data(event) slack_result = post_to_slack(slack_webhook_url, slack_data) if slack_result: logger.info('Function Normal End') else: logger.warn('Slack Webhook URL is Null.') return ログとかdocstringのお作法はこの時点では割と適当です。ごめんなさい。 動かしてみる StackSetsを管理しているus-east-1リージョンにてデプロイ後、適当なCFnテンプレートをSandbox用OUに展開して、テスト用アカウントをOU間で動かしてみたところ、以下のように無事リアルタイムでSlackに通知が来ました。 (念のため、ぼかさなくて良いようなところまでぼかしています) 良い感じですね。 ap-northeast-1リージョンのスタックインスタンスの結果までちゃんと拾えています。 通知のフォーマットは改良の余地がありそうですが、一先ず運用上は充分です。 ポイント 先にも触れましたが、サービスマネージド型StackSetsのイベントはOrganizationsの管理アカウントで発生します。StackSets管理用に委任したアカウントではありません。 Organizationsの管理アカウントで余計なリソースを管理したくない場合は、イベントバス転送で他のアカウントのEventBridgeに転送してやれば良さそう。 「StackSetsを管理しているリージョン」のEventBridgeであれば拾えます。スタックインスタンスがデプロイされるリージョン毎にEventBridgeルールを仕込む必要はありません。 あとがき 今回のAWSの対応で、StackSetsのデプロイ周りが簡単にリアルタイムイベントとして検知できるようになりました。 スタックインスタンス単位で通知が来るので、全スタックインスタンスのデプロイが終わるまで待つ必要もありません。 グリーンカレーを作る時間もなくなりました。 …昨年記事書いてた時は「仮にAWSが対応してこの記事が用済みになっても、レシピとして残そう」とか適当こいてたんですが、本当に対応していただけるとは!!!AWSさん神対応ありがとうございました!! 投稿 AWS CloudFormation StackSetsの自動デプロイ結果通知を簡単に受け取れるようになったのでやってみた は マイナビエンジニアブログ に最初に表示されました。
はじめに こんにちは、N.Tと申します。 今回は スマホで始めるRPA と銘打ってRPAを学んで3ヶ月目の新米エンジニアが記事を書かせていただきます。 ・RPAってそもそも何よ! ・RPA聞いたことあるけど、どんなことできるのよ! ・RPA触ってみたいけど始め方わかんなーい! という方にお勧めの記事となっています。 そもそもRPAとは? RPAとは"Robotic Process Automation"の略となります。 直訳すると "ロボットによる自動処理"で、 意訳すると "人間の行動をロボットに覚えてもらい、人間の代わりにロボットにその行動をしてもらうこと"、となります。 つまるところ、 "業務自動化" の意味合いで良く使われています。 本記事ではその一端となるものをおひとつ紹介しようと思います。 まずは準備を~アプリのインストール~ 今回扱うのはMicrosoft社提供の「PowerAutomate」です。 世界的に使用されているRPAソフトは有名なもので、「 UiPath 」「 WinActor 」「 BizRobo! 」等があります。 そんな中、比較的最近に無料公開されたPowerAutomate君はモバイルアプリver.もリリースされています! よって RPAをスマホでも始めること ができるわけです! また、PowerAutomate君はシステムに詳しくない人でも扱えるように、 多くのテンプレートが標準搭載されている のも魅力の一つなのかなと思います! 本記事ではそんなテンプレートを用いていきます。 毎朝お天気の通知をする! 私はテレビ離れをしてしまったZ世代なのです。 それゆえに毎朝テレビをつけて天気を確認するといった習慣はとうに消え去ってしまったのです…。 また、朝はできるだけぎりぎりまで寝ていたいタイプです。 コーヒーとトースト片手にベランダで優雅なモーニングに憧れていますが、憧れているだけでいつも寝ています。 出来るだけ、手間は排除したいですね...! ついでに毎朝欠かさずにモーニングメッセージくれる友人がいたらその日は元気に過ごせるでしょう! というわけで、エンジニアっぽくこれらの要求をまとめると、 朝起きたタイミングでその日の天気や気温が目に入るようにメッセージをくれる友人が欲しい! となります! そんな友人はどこにいるのだろう…? 答えはスマホの中にあります。 このあとの3ステップでその友人を見つけに行きましょう! 1st.テンプレートを開こう! 最初にアプリを開いてテンプレート検索窓に「天気」と打ちます! 出てきた検索結果から上記のテンプレートを選択、 開いたページから「このテンプレートを使用」を押下し、 以下のような画面が開かれるのを待ちましょう! 2nd.テンプレートをいじろう!~時間と場所の設定~ 続いて、本格的にテンプレートを触っていきます! 画像の赤ラインのように「Recurrence(再帰、周期的な起こり)」の中身の 「フロー名」を「毎朝お天気通知をする!」 「タイムゾーン」を「(UTC;09:00)大阪、札幌、東京」 「設定時刻(時間)」を「7」 にそれぞれ変更します! これで日本時刻の毎朝7時にこのロボット君は動いてくれるようになりました! それから、 「Get forecast for today(今日の天気予報を取得)」の 「場所」を「東京」に、 「単位」を「Metric」に変更します! これでロボット君は東京の天気予報をメートル法で取得してくれるようになりました! 3rd.テンプレートをいじろう!~通知方法と内容の設定~ テンプレートいじりも最終フェーズです! もともとあった「Send me an email notification(メール送信による通知)」を削除し、 別の通知方法を設定しようと思います! 下画像の「新しいステップ」を押した後、「アクションの追加」を選択します! 表示されたアクションの中から、 画像の通り、 「Notifications (モバイル通知を受け取る)」 を選択します! 無事選択ができたら下のような画面に切り替わると思います。 テキストの欄を自由に記述します! 今回は画像のように 「おはよう!今日の○○は、日中は○○で、夜は○○だよ!」 とテキストを用意し、 一覧表示される天気情報から「場所」、「日 条件」、「夜 条件」を埋め込んでいます。 これでロボット君がスマホの画面に設定したテキスト内容で通知が届けてくれるようになりました! いざ実行! さて、ここまでの流れでロボット君は 朝起きたタイミングでその日の天気や気温が目に入るようにメッセージをくれる友人! に本当になれたのかをチェックします! 画像の通り、 下部メニューの「フロー」を選択後、 「今すぐ実行」を押下します。 するとすぐにバナー通知が飛んでくると思います! 成功ですね! また、指定した時刻にもロック画面に通知を届けてくれました! 少々ネイティブですが... 終わりに 改めて、今回は スマホで始めるRPA といった内容の記事を書かせていただきました! 通知を飛ばしてくれるアプリを使えばもっと楽に天気を知ることができるかもしれないですし、デスクトップ版のRPAツールを用いれば人によってはもっと簡単につくってしまうかもしれません…! それでも、 RPAってスマホでも簡単に作れるんだ~ って思うきっかけになればいいな~と思って今回の記事を書いてみました! 少しでも多くの人に興味を持っていただければ幸いです。 今回は、私自身が初心者なこともあり簡単な内容にさせていただきましたが、 もっといろんな使い方ができるのでぜひ調べていただければと思います! また別の使い方を紹介できるように精進して参ります…! 投稿 スマホで始めるRPA~チュートリアル編~ は マイナビエンジニアブログ に最初に表示されました。
はじめに 突然ですが、この記事を読んでいるあなたには 「推し」 はいますか? 愛してやまない人やキャラクター、はたまたツールやプログラミング言語など、何かしら「推し」と呼べる存在がある人は多いのではないかと思います。 筆者にもいわゆる「推し」がいるのですが、ある日こんなことを思いました。 「推しの存在を業務中も感じていたい...!」 そこで今回は、筆者の切な願いを叶えるために、業務に欠かせない存在であるSlackのテーマカラーを、画像ベースで「推し」の概念を感じる色に変える方法を紹介したいと思います。 Slackのテーマカラー まずはSlackのテーマカラーについて仕様を確認します。 Slackでは、環境設定からテーマカラーを変更することが出来ます。 デフォルトで21種類のテーマを選択することが出来ます。 しかし、実はSlackでは自分でカスタムテーマを作成し、好きな色を設定することができます。 (参考: Slack のテーマを変更する | Slack ) それぞれの項目は以下の場所の色に対応しています。 補足 4. アイテムハイライト_ホバー時:サイドバーの項目をマウスオーバーした時に表示される色 6. アクティブアイコン:ユーザがオンラインの時にアイコンにつく印の色 これより、カスタムテーマを作るためには 9色 選ぶ必要があることがわかります。 方法の概要 カスタムテーマに必要な色数がわかったところで方法を紹介していきます。 以下の流れでSlackのテーマカラーを変えていきます。 画像からカラーテーマを抽出する 抽出したカラーをSlackのカラーテーマに割り当てる コントラストを確認しながら微調整する 画像からカラーテーマを抽出する まずは「推し」の画像を用意します。 今回は「いらすとや」さんからお借りしたこちらの画像を使用します。 ゆめかわ天使のイラスト | かわいいフリー素材集 いらすとや 「ゆめかわ天使ちゃん」です。かわいい。 推しの概念を感じる色、それはつまり推しを表現している色に違いありません。 推しの色を知るためには、画像上の色情報(カラーコード)を取得するカラーピッカーツールが便利です。 世の中には多くのカラーピッカーツールがありますが、今回は Adobe Color を使用していきたいと思います。 Adobe Color Adobe Colorを使う理由は以下の通りです。 無料で利用できる 画像に使われている色の数が多くても自動で数色に絞って抽出してくれる 操作が簡単&時短(休憩中にサクッと設定できる) コントラスト比を簡単に調べられる それではさっそくAdobe Colorを用いて色を選んでいきましょう! Adobe Colorで色を抽出する方法 Adobe Colorの 「テーマを抽出」 タブを選ぶとファイルをアップロードする画面になるので、説明の通りに画像を選択します。 すると画像の中でメインとなる5色を選択してくれます。 しかし、よく見るとイラストに使われていない黒(#0D0D0D)が選択されてしまいます。 これは元の画像の背景が透過されていることにより、透明部分が黒として認識されるため発生する事象となります。 このような場合や意図しない色が選択されてしまった場合は、ピッカーをずらして選択しなおすと良いです。 今回は目の色に使われている水色部分を選択しなおしました。 これで5色抽出することが出来ました。 一旦Slackに5色配置して、残りの4色を考えていきましょう。 抽出したカラーをSlackのカラーテーマに割り当てる カラーコードってなに? 各箇所の色はカラーコードで指定することが出来ます。 技術記事っぽくするために カラーコードについて軽く説明させていただきます。 カラーコードとはWebページ上の色指定で使われるコードで、シャープ(#)に続く16進数6桁で表されています。 コンピュータのディスプレイなどの光で色を表現するデバイスは、赤・緑・青の光の三原色を混ぜ合わせる(加法混色する)ことで色を表現します。 赤・緑・青は256段階の強さで光らせることができ、3色の強さの組み合わせで256×256×256=約1600万色を表現することが出来ます。 #の次に続く2桁が赤(R)、中央2桁が緑(G)、末尾が青(B)の強さを表します。 前述の通り、光の三原色がもとになっているので、#000000は黒になり#FFFFFFは白になります。 カラーコードの意味を知っておくと、コードからなんとなく色味がわかるようになります。 カラーコードにおける#の右隣の数値を1桁目にした時、1・3・5桁目がe~fであれば白寄りの色だな~とか、RとGの値が大きくてBが少ない時は黄色っぽい色だな~とかが掴めるようになります。 そんなことを思わなくても、世の中にはカラーコードを入れるとその色を表示してくれるサイトはたくさんあるので安心してください。 実はSlack上でカラーコードを入力しても色を表示してくれます。 さて、カラーコードの意味を踏まえたところで実際に配色していきましょう! 一旦配色してみる まずは画像から色の使われている面積を捉えます。 元にしたキャラの画像を見ると、髪と服のリボンに使われているピンク(#F29BBB)と、天使の輪や髪のリボンに使われている黄色(#F2DAAC)が広い面積に使われていることがわかります。 線の色に使われている薄い紫(#CAC4F2)や目の色に使われている紫(#B48FD9)や水色(#B9E5FF)はアクセントとして使われていることもわかります。 ここでもう一度カラーテーマと画面との対応を見ながら、面積通りに設定していきます。 今回はデフォルトテーマである「オーバージーン」をベースに、 サイドバー背景:ピンク(#F29BBB) トップナビゲーション:黄色(#F2DAAC) テキスト:薄い紫(#CAC4F2) アイテムハイライト_選択時:水色(#B9E5FF) アイテムハイライト_ホバー時:紫(#B48FD9) で配置してみました。(仮置きなのである程度お好みで色配置してもらっても大丈夫です) するとどうでしょう? 文字、読めない......。 いくら推しの色とはいえ、文字が読めず業務に支障をきたしたら本末転倒です。 これはコントラストを全く考えず配色してしまったため起きてしまった事故です。 次はコントラストを考えながら色を配置し、ついでに残りの4色も決めていきましょう。 コントラストを確認しながら微調整する コントラストとは、 「明暗の差」 のことです。 コントラストが高い、つまり明暗の差が大きいと色と色の境界がはっきりします。 なので文字をはっきり見せるには、背景色と文字のコントラストを高めることが必要になります。 コントラスト比は相対輝度を使って求めることが出来ます。 ざっくりと説明すると、黒の輝度を0・白の輝度を1とした時にコントラスト比を知りたい2色の相対的な輝度を求め、その比を計算することで求められます。 ※詳しく知りたい方は「相対輝度」や「Web Content Accessibility Guidelines (WCAG) 2.1」といった言葉で調べてみてください。 今回は計算する手間を省くため、Adobe Colorを利用してコントラスト比を求めてみます。 Adobe Colorのタブから 「アクセシビリティツール」 を選択します。 先ほどのテキストカラーと背景色を設定しコントラスト比を求めると 1.25:1となりました。 参考に、WCAG 2.1という基準では、「文字を見やすく表示するには 最低限コントラスト比が 4.5:1 必要 」という記載があります。 3分の1以下ですね!! ですが、これは誰にでも見やすいWebページを作るための基準なのでSlackで自分で使う分には絶対満たさなければいけない条件ではありません。 体感ですが、 2:1以上であればちゃんと読める と思います。 ※個人差もありますしディスプレイによっても変わります 色のついた四角をクリックするとカラーホイールを使って色を調整することができます。 明度を変えるだけではなく、色味(色相)を変えてもコントラスト比は変わるので色々いじって色を調整します。 個人的にコツは、 カラーホイールとカラーハーモニールール を使うことだと思います。 「これだけは絶対使う!」という色を1つ決めて、タブから 「カラーホイール」 を選び、その色をベースカラーに設定します。 そして、 カラーハーモニールール を変更した時に出てくる色を補助で使うと上手くまとまると思います。 また、カラーホイール上で距離が近い色はまとまりが生まれ、離れている色はアクセントになります。 ※この辺のテクニックは調べるとたくさん出てくると思います。 あとは、サイドバー背景の色は目が疲れないような色(白または黒に近い色が無難)をオススメします。 「テーマの抽出」に戻って、取得しなかった部分の色をピッカーで取得するのも良いと思います! 今回は、カラーハーモニールールの「類似色」を選択して得た色も使い、カスタムテーマを組みました。 完成!! というわけで完成しました! ポイントは 目の色に合わせてアイテム選択時のハイライトとテキストのカラーを合わせた アイテムハイライトのホバー時と選択時の色味を紫に合わせた サイドバー背景とテキストは、髪色のピンクと目の色の紫を調整して配色し、文字を読みやすくした トップナビゲーションに髪色に近いピンクと天使の輪やリボンの黄色を配色 メンションバッジのテキストカラーは白固定なので、メンションバッチの色はコントラスト比の高い色を選んだ という感じですかね! 正解はないので 自分がそこに「推し」の概念を感じられたら正解 です。 カラーテーマの共有 せっかくなので作ったテーマの共有をしてみます。 Slackにカラーコードをカンマ区切りで投稿するだけで、人に共有できるだけでなくそのままテーマを変更することが出来ます。 さらにカラーテーマ設定画面から、今使っているテーマのカラーコードセットをコピーすることも出来ます。便利! ぜひ、作ったテーマを共有してみてください! 今回作成したテーマと普段私が使っているテーマを共有します。 yumekawa-tenshi #FFDFEE,#FFF8D4,#B48FD9,#B1E2FF,#CAC4F2,#916DB5,#FFA1BA,#79CAF2,#FF9CB6,#FFEAAF Blossom Pink #FFE7E3,#89CFF0,#F77D8A,#FFFFFF,#FFC5AD,#F55358,#FFB12E,#DF3232,#EC686C,#FFFFFF オマケ 「とはいえ作るの大変...。」「もっとサクッと作れないの?」「推しなんていないから、キャラクターの画像以外からも良い感じに作れない?」という声もあるかと思うので、他の方法も少し共有させていただきます。 カラーテーマ配布サイトを使う Slack Themes : https://slackthemes.net/#/jellybeans 例えば上記のようなカラーテーマ配布サイトを見て、お気に入りのカラーテーマを見つけるという方法があります。 IDEを模した配色はこのようなサイトで配布されている場合が多いです! ぜひ探してみてください。 写真から色を抽出する Adobe Colorでは色数の多い写真からも色を5色抽出することができます。 お気に入りの風景写真やCDジャケット・衣装の写真などからも、同様の方法でカスタムカラーテーマ作成が出来ます。 Adobe Colorの「探索」機能を使う Adobe Colorには 色を言葉から検索する機能 があります。 ここから自分好みの色を探してから作れば楽にカラーテーマの作成ができると思います! 最後に ここまで読んでいただきありがとうございました! 今回はSlackのカラーテーマに絞って解説しましたが、色の選び方やAdobe Colorといったサービスの使い方は、資料作成に使ったり他のところでも応用できると思います。 働いている時間であっても、少しでも遊び心や楽しい気持ちを感じていただけたら幸いです。 投稿 Slackを「推し」色に染める ~オリジナルカラーテーマの作り方とコツ~ は マイナビエンジニアブログ に最初に表示されました。
はじめに この記事では、AWSの資格であるSAAを取得したもののそこまでAWSを触っていなかったAWS初心者が、業務にそこまで影響がない範囲内でAWSでなんか作ってみようと思い立ち、学習目的半分で試行錯誤した結果触ってみて初めて知った苦労などを記載しています。 AWSを日常的に触っている人にとっては知ってる内容かもしれませんが(もしくは触ったことなくても別に躓かないかもしれない)、AWS初心者でかつ日常的にコードも書かない、データベースの扱いにも全く慣れていない人間としては苦労したポイントがいくつかありました。 「そんなんも知らんのかプークスクス」と笑わずに大目に見てくれると嬉しいです!! 目指したもの Slackのフリープランでも90日前のメッセージを遡れるシステム きっかけ 2022年9月1日からのアップデートで、フリープランだとSlackで共有されたメッセージやファイルは90日経過後に閲覧できなくなりました。 社内のコミュニケーションにメイン使っているエンタープライズプランのものとは別に、アラート発報用のワークスペースをフリープランで契約しており、Slackでの契約プランは変更せずなんとか90日経過後でもメッセージが遡れるようにできないかという思いから作ってみました。 作ったシステムの概要 簡易構成図 大体の仕組み EventBridgeで毎月1回Lambda実行し、Slackに全メッセージを取りに行く Lambdaで取得したメッセージのファイル形式を変換し、S3に保管する Athenaで取得したい要件に合わせてクエリを投げる チャンネル名、日付、etc... 90日経過で消えるので月一じゃなくてもいいのですが、万が一コケた時に気付くのが遅れないよう月一実行にしました。 ※2022年8月のまだプラン内容が変わる前に、下準備として取り急ぎ全メッセージ取得しておきました。90日過ぎたら泣いても笑ってもプラン変更しないとメッセージ取得できませんのでご注意ください。 また、通常ログの保存や検索にはElasticSearchを使うのがベストプラクティスかと思いますが、今回は以下を理由にAthenaを採用しました。 クエリごとの課金となるので比較的コストを抑えられる システムの使用頻度的に、正直そこまでクエリ投げないであろう想定 サーバレスなのでインフラの面倒を見る必要がない クエリできるデータ形式が豊富である 正直に言うとAthenaを良い感じに使ってみたかった(本音) 個人的に苦労した実装に対しての感想 何度でも言いますが、大目に見てください... Athenaでクエリできるファイル形式がなんか思ってたのと違ったんだけど Athenaでクエリできるファイル形式としてcsv、parquet、jsonなどが公式で紹介されています。 AWSユーザーガイド : サポートされる SerDes とデータ形式 今回はSlackの検索結果がJSON形式で簡単に取得できるためJSON形式を選びましたが、 厳密には単なるJSONではない ことにすぐ気付けず、少し悩んでいた時間がありました。 公式ドキュメントには、サポートされるJSON形式について以下のように説明されています。 JSON (JavaScript Object Notation) JSON データでは、各行がデータレコードを表します。 各レコードは属性/値のペアと配列で構成され、それぞれがカンマで区切られます。 つまり、複数レコードの場合は、 [ {"key1": "value1", "key2":"value2"}, {"key1": "value1", "key2":"value2"}, {"key1": "value1", "key2":"value2"} ] ではなく、 {"key1": "value1", "key2":"value2"} {"key1": "value1", "key2":"value2"} {"key1": "value1", "key2":"value2"} としてファイル出力する必要があり、この形式は JSON Lines と言われている書式となります。 つまり、取得したJSON形式のファイルを更にJSON Lines形式へ変換する必要があります。 JSON Lines形式を扱う方法はpandasなどいくつかありますが、今回は jsonlines のライブラリを使って実装しました。 import jsonlines content = [ {"key1": "value1", "key2":"value2"}, {"key1": "value1", "key2":"value2"}, {"key1": "value1", "key2":"value2"} ] path = "/your/path/to/store/file.json" with jsonlines.open(path, mode="w") as writer: writer.write_all(contents) JSON形式と言われると、通常はファイル全体がJSONオブジェクトとして解釈可能である必要と思い込んでいました。 自分としては正しいJSON形式で出力しているにも関わらず、Athenaでクエリが失敗するため、何故…となり、地味に調査に時間がかかったポイントでした。 Athenaを使ったことがある方なら知っていることかもしれませんが、Athena初体験だったので印象に残っています。 S3にファイルをアップロードする際の暗号化の仕方ってマネージメントコンソール使わない時どうすればいいの? S3にファイルをアップロードする際、何らかの暗号化を施すことが多いかと思います。 マネージメントコンソール上で操作する際は画面上で選択すればよさそうですが、API上でどう指定すればいいのか知らなかったため苦労しました。 API上では、呼び出す際に指定する引数に以下のように ExtraArgs 内で指定するとSSE-S3により暗号化され、アップロードできます。 import boto3 bucket_name = "bucket name" object_name = "object name" s3 = boto3.resource("s3") s3.Object(bucket_name, object_name).upload( ExtraArgs={ "ServerSideEncryption": "AES256" } ) ちなみに、ここで AES256 を aws:kms に置き換えると、AWS KMSと連携して別のキーで暗号化できるため、ここは要件によって変えればよさそうだなと思っています。 Athenaのスキーマ作成の手間が思ってたより多くて諦めそうだった AthenaでJSONをクエリするためには、テーブルを作成する必要がありましたが、通常のSQLとスキーマの定義方法が異なります。 特に、 ネストしたJSONをテーブル上で定義する SQLとのデータ型の違い 暗号化・GZIP圧縮した元データの参照方法 は、テーブル作成において何度か詰まって確認したポイントです。 ただでさえデータベース苦手なので、何言ってんだこりゃあ…となりました。 以下は実際に作成したスキーマです。 CREATE DATABASE IF NOT EXISTS your_database LOCATION 's3://your-bucket/'; CREATE EXTERNAL TABLE IF NOT EXISTS `your_database`.`your_table` ( iid string, team string, channel struct< id: string, name: string>, type string, user string, username string, ts timestamp, text string, permalink string ) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' WITH SERDEPROPERTIES ( 'ignore.malformed.json' = 'FALSE', 'dots.in.keys' = 'FALSE', 'case.insensitive' = 'TRUE', 'mapping' = 'TRUE' ) STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 's3://your-bucket/' TBLPROPERTIES ( 'has_encrypted_data' = 'true', 'classification' = 'json', 'write.compression' = 'GZIP', 'classification' = 'json' ); テーブル定義内の channel のカラムで、このキーはJSON上ではネストしたオブジェクトとして表現されていました。 このようなデータはAthenaでは struct(構造体) と表現されています。 AWSユーザーガイド : Amazon Athena のデータ型 今回は、 channel のオブジェクトの内一部が必要だったため、構造体として以下のように定義しました。 channel struct< id: string, name: string>, また、 timestamp にはJSON上では小数点付きのUNIXエポック時間が格納されていますが、このままでは不便なのでこのカラムには timestamp型 を設定しました。 これにより、日時でクエリしたい場合は、 SELECT * FROM "your_database"."your_table" WHERE ts > timestamp '2022-10-25 00:00:00' のように、日付文字列で直観的に検索が可能となります。 さらに、今回は参照するオブジェクトをSSE-S3による暗号化とGZIP圧縮しています。 そのため、テーブル定義の TBLPROPERTIES セクションにて以下のように指定しました。 TBLPROPERTIES ( 'has_encrypted_data' = 'true', 'classification' = 'json', 'write.compression' = 'GZIP', 'classification' = 'json' ); これで、元データが圧縮かつ暗号化されたデータでもクエリしてくれるようになります。 ちなみにですが、今回はAthena検索時のS3のパーティションは分けずに進めています。 ファイルは月毎に生成される想定なので、クエリを投げる際は全文検索のようになり、パーティション分けても分けなくてもこのシステムの構成上変わりはないです。 しかし、ファイル保存量が多かったり、クエリを投げる際の条件でもっと絞れるようでしたら、パーティションを分けた方が費用面でとてもよいです。 Amazon Athenaの料金 現在はこのシステムを作ったばかりなのでファイル量が多くなく、クエリ回数が少なく済んでいますが、今後のことを考えるとファイル保存方法の仕様を見直したいと思います。 EventBridge「cron式です(大嘘)」 EventBridgeで毎月実行のスケジュール登録する際、普通のcron表記と書き方が違ったのでおや…と思った部分になります。 今回はマネージメントコンソール上でやってたので時間がかかったとかよくわからなかったとかではないのですが、マネージメントコンソールを使わず設定してたら詰まったかもしれないなと思います。 AWSユーザーガイド : ルールのスケジュール式 例えば、毎月6日の7:00に実行する、というのを書こうと思うと 0 7 6 * * となると思いますが、AWSのドキュメントでは以下のように記載されています。 ? (疑問符) ワイルドカードは任意を意味します。 [日] フィールドに 7 と入力し、7 日が何曜日であってもかまわない場合、[曜日] フィールドに ? を入力できます。 さらに、最後尾には年も指定することになります。 今回は下記のようになります。 0 7 6 * ? * 実際の設定画面はこちら↓ マネージメントコンソールに従って設定していくとそこまで時間のかかる躓きポイントではないのですが、気になったのでいろいろ調べてみると下記の記事を見つけました。 記法に注意が必要そうな場面も出てきそう、ということで覚えておこうと思います。 参考 : クラスメソッド AWSでのCron表記でハマったので仕様を確認しておく なんやかんやあってできあがったもの こんな感じのものができました。 例えば、チャンネル名を指定して、指定のチャンネル内で交わされた全メッセージを見てみたいと思います。 見せられる部分が少なくて恐縮ですが…一応当初の想定通り、90日以上前のメッセージも取得できています。やったね! おわりに 今回はAWSの学習目的の元、Slackメッセージを取得しておいていつでもメッセージを見ることができるシステムを作りました。とりあえず動いてはいます。動いてるってすばらしいね。 ここまで書いておいてすごい今更なのですが、メッセージ数によっては有料プランに変更した方が結果的に安く済むかもし楽じゃない?、みたいな見方ももちろんあります!!ただ、今回のことを通じて1つ勉強になったので、良い機会だったなと思います。 まだまだ改修すべき点や設計を見直したい箇所、考慮漏れもありそうですが、とりあえず今動かしている部分で書ける分だけ今回記事にしてみました。 今後勉強すると共に、定期的に見直していきたいです。 今回の体験で、資格取得だけでは知り得ない世界を少し垣間見ることができてとてもよかったです。 お読みいただきありがとうございました。 投稿 普段AWS触ってない人間がLambdaとAthenaでなんか地味に苦労した話 は マイナビエンジニアブログ に最初に表示されました。
はじめに こんにちは。 プロセスデザイン部 コミュニケーションデザイン課です。 ITを通じコミュニケーションを最適化する ことをミッションとして、今年の4月に新しく発足した部署です。社内のコミュニケーションを活性化させることで「 横串の業務改革 」や「 サイロ解消 」を目指しています。 今回は組織の紹介も兼ねて、私たちがどのような活動を行っているのかを書いてみたいと思います。 どんなことをする部署? ITの企画部門 私たちは全社のITを管理する部門の中で、 今後の社内のIT環境を考えることを専門としている企画部門 です。 企業は常に変化し続けていかなければならず、 それに対応して社内のIT環境も変化し続けていく必要がある と考えています。 DX推進PJに参加 マイナビでは、IT部門だけでなく総務や経営企画といった管理部門と、事業部の有識者を集めて全社横断のDX推進PJを発足しています。 DX推進PJでは「横串の業務改革」「データ利活用」など様々なテーマを扱っています。私たちはその中の「 サイロ解消・情報共有 」に関する分科会に参加しています。 コミュニケーションの活性化を目指して サイロ化ってなに? 「サイロ化」という言葉を知っていますか? 組織ごとに業務プロセスやシステムなどが独自に存在し、全体で連携できていない状態のことを指します。 特に、企業で部署同士が縦割り状態になり、部署間の横の連携が取りづらい状態のことを「 組織のサイロ化 」と呼びます。 組織の縦割り状態は、各部署が各々の役割に専念できるというメリットがある一方で、互いが何をしているのかがわからないため、 企業全体でみたときには効率が悪く成長を阻害する 要因ともいわれています。 私たちの部署では、社内のコミュニケーションを活性化させることで、サイロ化を解消することを目指しています。 オープンコミュニケーションが大事 私たちの部署のミッションを達成したとき、マイナビはどのような状態になっているんだろう? 組織が発足したときにみんなで考え、以下のような状態を"目指すべき姿"としました。 組織を横断したコミュニケーションが活発化することで、 今まで共有されていなかったナレッジが共有されたり、新しいコラボレーションがうまれる など、様々な化学反応が起きる状態 そのためには、誰もが見られる場所でコミュニケーションをすること= オープンコミュニケーション が重要になると考えています。 まずは社内の課題を洗い出す 今年の4月に部署が発足してから、まずは社内のIT環境の実態を調べることから始めました。 サイロ化は本当に起きているのか?何か原因となっているツールがあるのか?など、今後のあり方を考えるために現状の課題を知ることを目的としました。 マイナビ社員約7,000人を対象にしたアンケート調査と、全国の様々な職種の社員15名にインタビューを実施しました。 社内調査をスクラムですすめてみた 社内の課題を洗い出すプロジェクトでは、運営をアジャイルの代表的な手法である「スクラム」をベースとして行うことにしました。 スクラムというとシステム開発で用いられるのが主流ですが、今回のような システム開発ではない案件にも適用できます 。 スクラムを用いることにした背景は大きく分けて2つあります。 一つ目は「 チームメンバーがほぼ全員初対面同士であったから 」です。 コミュニケーションデザイン課とEX推進課という二部署共同でおこないましたが、どちらも2022年4月に新設されたばかりでした。3月までの職種や業務内容もみんなバラバラでした。 それぞれ価値観にギャップがあり、プロジェクトに対する目線を合わせるのが難しい状況だったのです。 そのため、コミュニケーションをとる頻度が多くなるように工夫されているフレームワークを用いたいと思い、スクラムを取り入れることにしました。 二つ目は、「 全社的な規模でのアンケート実施を行った実績がなかったから 」です。 IT部門が主催する調査としては前例がないものであり、ノウハウや工数などが非常に不透明な状態で進める必要がありました。 そのため、プロジェクトレベルで見ても臨機応変に動くことのできるよう、工数を相対的に見積もりつつスプリント単位で動きを変えることのできるスクラムを取り入れることにしました。 スクラムの経験値があるメンバーは過半数以下でしたが、 初動で丁寧にスクラムについて説明を行った ことで上手く浸透し、プロジェクト自体もスムーズに進行することが出来ました。 皆さんも、 初対面のメンバーで新規案件を取り扱う場合には、スクラムで進めてみてはいかがでしょうか? これから取り組むこと 社内調査でわかったこと ITツールに関する社内調査によって、同じような役割のツールが社内でたくさん使われていることがわかりました。 特にチャットツールは、IT運用部門が管理している全社導入済みのツールが2種類あるほか、各現場が独自に導入しているツールも散見されました。 各現場によってメインで使っているツールが違う 状態です。 ツールが異なることにより、他事業部と連絡したいときに何のツールを使えばよいかわからなかったり、色んなツールから連絡がくるので通知を見落としたり、どこでやり取りしたか分からなくなるなど、 ちょっとした不便が起きている ことがわかりました。 ▼各コミュニケーションツールの利用率 C~Eは現場が独自で導入しているチャットツールですが、多いものだと約3割の社員が使っているという状況です。 インタビュー調査から、メールを含めると 常時3~4つのツールを使い分けている 社員がいる(!)こともわかりました。 社内の交通整理が必要 こういった状況を受けて、社内向けにチャットツールのガイドラインを作成しました。 マイナビで利用可能なツールを一覧化し、利用を推奨するツールや各ツールの特徴、現場で独自に導入する場合の申請方法などをまとめています。 社外からの要請などやむを得ない事情もあるので、利用するチャットツールをひとつに限定することは難しいと考え、まずは 社内のやり取りのスタンダードを決めて社内に発信 しました。 とはいえ、ツールの数の多さ自体にも問題があると考えており、今後は抜本的な見直しも図っていきます。 まだ結論は出ていませんが、今後 社内のチャットツールを統一し、全社共通のコミュニケーション基盤を構築していく 想定です。 ツールを統一するだけでよいの? 残念ながら、社内の チャットツールをひとつにしただけでは、コミュニケーションは活性化しない と考えています。 部署を横断したやり取りや新しいコラボレーションが発生する状態になるためには、 オープンコミュニケーションの文化をつくっていく 必要があります。オープンな場で気軽に発信できるような、心理的安全性が確保されている組織風土の醸成です。 文化や風土の醸成は、一朝一夕でできるものではありません。 コミュニケーション基盤を構築した後には、その環境をどのように使ってもらうかを考えながら、 オープンコミュニケーション文化を醸成できるよう、様々な仕掛けをおこなっていきます! 投稿 DX推進のために社内ITツールの利用状況を調査した は マイナビエンジニアブログ に最初に表示されました。
はじめに AIシステム部のS.Kと申します。 今回はAtCoderで水色まで到達した身として、さまざまな場面で役に立つ計算量についてまとめていこうと思います。 計算量という概念はアプリケーションに必要な計算リソースを見積もるのに便利な道具です。 従量課金制のクラウドサービスが主流 になっているこの世の中で、必要な 計算リソースを意識するのはとても重要 です。 また、AtCoderをしていると、嫌でも 計算時間 を気にする必要があります。基本的に1回の実行に対して 実行時間は2秒まで という制限があるからです。自分が書いたソースコードの実行時間が2秒程度で収まるのか、計算量を考えるとおおよその見積もりが立ちます。 アルゴリズムの性能を測る上で避けては通れないキーワード 「計算量」 について、可能な限り分かりやすく解説できればと思います。 計算量って何? そもそも計算量とはなんでしょうか? 計算量という概念は主に計算複雑性理論で使われる言葉です。 計算複雑性理論のWikipedia ではこんな記載がありました。 以下引用 アルゴリズムの計算量(けいさんりょう)とは、計算機がそのアルゴリズムの実行に要する計算資源の量をいい、アルゴリズムのスケーラビリティを示す。形式的には計算機をチューリング機械やランダムアクセス機械(random access machine)などの計算モデルとして定式化したうえで、アルゴリズムの使用する資源の量を入力データ長などに対する関数として表す。計算モデルの瑣末な詳細に影響を受けないよう、計算量はその漸近的な挙動のみに注目し、定数倍を無視するO記法で書き表すことが多い。 えーーっと……? よく分からないので コトバンクの「計算量とは」 のページを見てみましょう。 以下引用 世界大百科事典 第2版「計算量」の解説 けいさんりょう【計算量 computatinal complexity】 アルゴリズムの計算効率や問題の難しさを測るための尺度。主なものに,時間効率を測るための時間計算量,メモリー効率を測るための領域計算量などがある。他にも,計算回路の性能を議論するための計算量や,分散処理でのプロセス間の通信効率を測るための計算量など,用途に応じてさまざまな計算量が用いられている。 コンピューターで仕事を処理したり問題を解く場合,計算手順(アルゴリズム)の善し悪しで,プログラムの計算時間や使用する記憶容量が大幅に異なってくることが多い。 少し分かってきました。まとめてみると、計算量とはこういう概念です。 計算量の代表的なものとして、 時間計算量 と 領域計算量(空間計算量とも言う) がある。 計算手順の良し悪しで、必要な計算時間や記憶容量が異なる。 時間効率を測るのに時間計算量が用いられる。 メモリー効率を測るのに領域計算量が用いられる。 他にも用途に応じてさまざまな計算量が用いられている。 すなわち、以下の二つのことが言えます。 時間計算量が小さい→計算時間が短い 領域計算量が小さい→必要な記憶領域(メモリ量)が少ない なので基本的に 「計算量が小さければ小さいほど、いいアルゴリズムである」 と言っていいでしょう。 計算量の記述方法「ランダウの記号」とその意味 計算量を記述する方法として「ランダウの記号( 参考:Wikipedia )」が用いられます。\(O\)という記号を使った、このような記述方法です。 このアルゴリズムの時間計算量は、入力とするデータの個数を\(n\)とした時、\(O(n)\)である。 「\(O(n)\)」の部分は「オーダー \(n\)」と読みます。これの意味は 「このアルゴリズムの時間計算量は、入力とするデータの個数に(\(n\)に)比例する。」 という意味です。言い換えると、「データの個数(\(n)\)が倍になると、計算時間も倍になる」という意味になります。 このカッコの中身は、任意の\(n\)についての関数が入ります。 具体例を見てみましょう。 時間計算量が \(O(n^2)\) 時間計算量は\(n\)の2乗に比例する。つまり、\(n\)が2倍になると計算時間が4倍になる。 \(n\)が増加すると、 計算量が\(O(n)\)のアルゴリズムよりも計算時間が長くなりやすい 。 時間計算量が \(O(\log(n))\) 時間計算量は\(log n\)に比例する。つまり、\(n\)が2倍になると計算時間は\(log2\)増加する。 \(n\)が増加しても、計算時間は少しずつしか長くならない。 時間計算量が \(O(2^n)\) 時間計算量は\(2^n\)に比例する。つまり、\(n\)が2倍になると、計算時間が\(2^n\)倍になる。 \(n\)が少しでも増加すると、計算時間がとても長くなる。 時間計算量が \(O(c)\) (cは実定数とする。) 時間計算量は 常に一定 である。つまり、\(n\)が増加しても計算時間は変化しない。 つまり、この記述が表すのは 「データ量 \(n\) が増加(減少)した時、処理時間がどの程度増加(減少)するか」 なのです。計算量が空間計算量の場合は、 「データ量 \(n\) が増加(減少)した時、処理に必要する記憶領域がどの程度増加(減少)するか」 を表すことになります。 計算量が\(O(log n)\)であれば、データ量が増えるとしても、計算時間はそこまで長くならないので対して心配する必要はありません。しかし計算量が\(O(2^n)\)であれば、少しでもデータ量が増えると、計算時間がとても長くなってしまう、ということが分かりますね。 この様に計算量は何か基準となる変数(上記の場合は\(n)\)を決めて、それを使って記述します。\(n\)の取り方は他にも以下の例があるでしょう。 入力が文字列\(S\)の時、文字列\(S\)の長さ(文字数) 入力が整数\(N\)の時、\(N\)そのもの \(N = 2^n\)と表した時の\(n\)、(すなわち\(log N\))を基準とすることも多いです。 入力がグラフ構造を持つとき、その頂点の数。 色々書きましたが、ここでは、 「\(O(n)\) (オーダー \(n\) )ってそういう意味なのか!!」 というのが伝われば大丈夫です。そして 「\(n\)について増加しやすければしやすいほど、計算量が大きい」 ということに気を付けましょう。 詳しい数学的な定義が気になる方は、 ランダウの記号のWikipedia に十分な記述がありますので、目を通していただければと思います。 計算量の求め方 では、具体的な計算量の求め方を見てみましょう。今回は時間計算量に焦点を当ててみようと思います。 以下のPythonのソースコードを見てください。 cnt = 0for x in range(n): for y in range(n): for z in range(n): if x + y + z == w: cnt += 1print(cnt) このソースでは0以上\(n\)未満の整数3つの組み合わせで、その和が w になるものがいくつあるかを計算しています。 このソースの計算量は\(O(n^3)\)になります 。 この計算量になる理由は、 「【x+y+zがwと一致しているか】を確かめる演算を合計で\(n^3\)回するから」 です。forループの中の演算が何回行われるかを数えればいい訳ですね。 では次のコードを見てみましょう。 cnt = 0for x in range(n): for y in range(n): if 0 <= w - x - y < n: cnt += 1print(cnt) これは1つ前のコードと全く同じ結果を出力します。wと、2つの整数の和の差が0以上 \(n\) 未満であれば、整数3つの組み合わせで、その和がwになるものが存在するからです。 このソースの計算量は\(O(n^2)\)になります 。 「【w-x-yが0以上、\(n\)未満であるか】を確かめる演算を合計で\(n^2\)回するから」 が理由です。 計算量を求める場合はこのように、 「演算を行う回数を\(n\)を用いて記述した式」 を考えればよい訳です。これを考えることで、\(n\)が増加すると計算時間がどの程度長くなるのかが分かる、という訳ですね。 こうして計算量を考えることで、「処理の内容が同じだとしても、記述の仕方で処理速度がどの程度変化するか」を定量的に把握することができるのです。 ライブラリを利用する場合 現在のアプリケーション開発において、ライブラリの利用は不可欠なものです。そうなった時、 アプリケーション全体の計算量 を見積もるためには、 ライブラリで提供されている関数や、クラスのメソッドの計算量 を把握しておく必要があります。 これに関しては以下の対応が必要かと思います。 ドキュメントから仕様を確認する。 どのような処理を行っているのかドキュメントを確認し、その処理に必要な計算量を見積もる。 場合によっては計算量そのものの記載がある。 ドキュメントのみからでは正確な見積もりができない場合もある。 実際のソースコードを読み込む。 上記の手法で計算量を見積もる。 かなり正確な見積もりができるものの、ドキュメントを読むよりも時間がかかることが想定される。 どこまで正確な見積もりが必要になるかは、ケースバイケースだと思います。実際に実行した時の処理時間を計測した方が有効な場合もあるかと思います。 業務での計算量 例えば、Webアプリの計算量(時間計算量、空間計算量の両方)を小さくすると、以下のメリットがあるかと思います。 バックエンドでの計算量が小さい時 ユーザーの待ち時間が短くなる。 処理時間に対して従量課金がある時、利用料金が安く済む。 使用したメモリに対して従量課金がある時、利用料金が安く済む。 フロントエンドでの処理時間 ユーザーのPCにかかる負荷が軽減される。 UI/UX改善に繋がる。 フロント側の処理が重くても待ち時間の増加に繋がります。 以下のような場合は特に、より正確な計算量の確認が重要でしょう。 処理で取り扱うデータの量が膨大なとき。 計算リソースに制限があるとき。 「どの処理について」の計算量を考えるか 先ほどは時間計算量を比較演算の回数で見積もりました。しかし、どの処理の回数を基準として計算量を見積もるかは場合によって変わると思います。以下のような処理の回数はとても重要です。 外部との通信の回数と容量 回数や容量が多いことは、帯域の圧迫であったり、余計な費用増加に繋がります。 API等を利用する際は、APIの呼び出し回数に制限がある場合もあります。 DBにアクセスする処理の回数 回数が多いとDBの負荷が増加します。 クエリ回数に対して課金があるDBサービスもあるかと思います。 パスワードやトークン、秘密鍵といった機密情報が必要な処理の回数 特定のソースコードというよりかは、システム全体の設計で意識することかと思います。 計算量を定義する際に、 「他にも用途に応じてさまざまな計算量が用いられている。」 と述べたのはこれが理由です。「上記の処理の回数を少なくすることで、処理時間が短くなる」 という訳ではない こともあると思います。計算時間を短くすることを優先するべきなのか、はたまたDBの負荷を減らすべきなのか。 システムの仕様や要件と相談する必要があるかと思います。 計算量は常に考えるべきなのか ここまで計算量を小さくして、処理を効率化することばかり論じてきましたが、 計算量をあまり気にしなくていいケース もあります。 データの量や長さが固定、あるいは少ないとき システムの仕様上どうしてもその処理が必要なとき この様な場合は計算量が多少多くなっても問題ないかと思います。 なぜこのような場合をわざわざ論じたかと言うと、 計算量を小さくすることで以下の問題が生じる 可能性があるからです。 処理内容の無駄を極力省いた結果、他者がそのソースコードを読んだ時に、どんな処理が行われているのかが分からない。 特定の処理を効率よく行うことに特化するあまり、再利用性が損なわれてしまう。 効率がよいコードを書こうとするあまり、コーディングにかかる時間が長くなってしまう。 これらの問題から、 常に計算量を小さくするべき とは単純に断ずることができない部分があります。システムの要件や仕様、場合によっては納期も考慮した上で、どのような実装を行うべきなのか判断するべきです。 AtCoderにおける計算量 この章は競プロに取り組もうと思っている方向けです。 AtCoderにおいて意識するべき数字があります。それは \(O(10^8)\) という数字です。 AtCoderでは、実行時間が2秒に制限されています。これを超えないためには \(O(10^8)\) あたりが限度だということです。これを超えたアルゴリズムはTLE(実行時間制限オーバー)になる場合が多いです。 入力が長さNの配列として与えられる場合を考えてみましょう。 AtCoderにおいては、Nの最大値が制約として与えられています。そのため、それぞれの制約に対して、「これくらいの計算量ならTLEにならない」という目安を書いておきます。 \(N\)が最大で \(10^2\) \(O(N^3)\)のアルゴリズムを動かしても問題ないでしょう。 多くの場合、特に計算量を減らす工夫をする必要もないかと思います。 \(N\)が最大で \(10^3\)~\(10^4\) \(O(N^2)\)あたりが限度でしょう。 \(N\)が最大で \(10^5\)~\(10^6\) \(O(N \log N)\) あたりが限度でしょう。 一つ一つの処理が重い場合は\(O(N)\)にするべきかもしれません。 これはクイックソートの計算量にあたります。ソートができるのはこの辺りまでです。 2重ループによる全探索は難しいです。 \(N\)が最大で \(10^7\)~\(10^8\) \(O(N)\)が限度でしょう。 \(N\)が最大で \(10^9\) \(O(N)\)で軽い処理ならギリギリTLEにならないでしょう。 そもそも入力に\(O(N)\)時間がどうあがいてもかかります。処理が軽ければ間に合うはずです。 \(O(\log N)\)や定数時間(\(N\)に依存しない時間)で処理が終わるものが理想です。 表にまとめるとこんな感じです。慣れてくるとこの表がなんとなく頭に入ると思います。 \(N\)の最大値 計算量 備考 \(10^2\) \(O(N^3)\) 計算量を考慮する必要はほとんどない。 \(10^3\)~\(10^4\) \(O(N^2)\) \(10^5\)~\(10^6\) \(O(N \log N)\) クイックソートによってソートを行うことができる。 \(10^7\)~\(10^8\) \(O(N)\) \(10^9\) \(O(\log N)\) 若しくは\(O(c)\) 処理が軽いのであれば\(O(N)\)でもいける可能性あり。 AtCoderでは、 難易度が高いほど入力長の最大値が大きくなる場合が多いです 。そのため実装に工夫や知識が必要になってきます。なのでAtCoderで上位になるためには、計算量(主に時間計算量)が小さくて済むアルゴリズムについて学び、それを実装する技術が必要です。 すなわち、 優秀な色の持ち主はアルゴリズムに対する知識が深く、その応用方法を熟知している という訳です。 まとめ 私は競プロや研究のために計算量について学びましたが、気がつくと常に意識するようになっていました。まずはなんとなくでもこれを理解し、できるだけ計算量が小さくなる実装を心がけることは大事だと思います。 計算量が小さくなるような実装を行うには、様々なアルゴリズムの知識が必要になることがあります。その知識が足りていなかったとしても、「これから書くプログラムの計算量、これくらいかな…?」と分かるだけで、相談することや、実際に動作させたときに何が起こるか想像することができます。 まずは「この処理の計算量はこれくらいかな…?」と考えるところから始めてみてはいかがでしょうか。
はじめに 皆さんこんにちは!開発系の部署に配属された、2022入社新卒R.Mです! メイン業務はモバイルアプリ開発で、Flutterを使用しています! 学生時は生命科学系を専攻してましたが、3年生くらいからプログラミングに興味を持ち始めて、簡単なiOSアプリを開発してました。 研究はPythonを使って、創薬に関することを色々やってました。技術を学ぶことも楽しいですが、ビジネス関連の話を聞くのも楽しい人間です。 ちなみに、趣味の中で今一番熱いのがK-POPです🔥 背景 この記事を書こうと思った理由・背景なのですが、自分自身配属されてから、触ったことのない技術(Flutter・Dart)を、社内で教えてくれる人がいない中で開発ベンダーさんと協力しながら勉強し、約2ヶ月間過ごしてきました。 はじめは課長とベンダーさん、自分含めて4人で定例会議を行っていましたが、今では一人でベンダーさんと進捗共有などを行い、プロジェクトを進行しています。 新卒でこれらの経験は中々無く貴重であり、得られたものも多かったと思っているので、 プロジェクトを進めていく会議上でやったほうが良い! と思ったことを個人の主観でまとめてみました🎉 ⚠️やっておくと良いと書いてますが、絶対必要でしょ!っていう意見もあると思うのでそこはご了承ください。 具体的にそれをどうやるかまでは書いてません🙏 【1】情報を同期すること 情報を同期するとは: 会議に参加しているメンバー全員が、プロジェクトに関して知らない情報を共通認識として持つことを指しています! 私達のチームは開発タスクをここで共有しているのですが、この仕組みがあるだけで、 新しいタスクはあるか 既存のタスクの状況はどうなっているか 未対応・対応中・対応済み どのバージョンでこの機能(タスク)を実装するのか ※スマホアプリなので、バージョンごとにリリースする機能を事前に話して決めます このタスクにかける時間はどのくらいか このタスクは誰が担当するのか などを決めることができ、その場のメンバーに共有もできます。 これらができていれば、、、 ■タスクが終わっていれば順調と判断でき、終わっていなければその原因と課題、次への対策まで検討が可能! ■タスクの管理漏れがなくなる!🔥 →今日、誰が何をしているのかが分かり、PMも全体状況を把握しやすい! 【2】ロードマップを立てること スマホアプリ開発の場合では、 バージョンごとに、「いつ」そのバージョンを世にリリースするかを決定 タスクごとに、「いつ」そのタスクを「どの」バージョンに含めるかを決定 タスクにかかる時間を元に、1スプリントで完了させるタスクを決定 スプリント = 単位の無い一定の期間。私達は1スプリント = 1週間と定義しています〜 これらをロードマップを立てる、として実施しています。 これらができていれば、、、 ■いつまでに、何が終わるのかが見やすい! →臨機応変に、プロジェクト進行の調整を行うことができる! ■次スプリントのスケジュールも立てやすい! →仮に1週間程度で5個くらいのタスクを終わらせたとすると、次の1週間にタスクにかける時間の目安もすぐ分かる! 【3】パーキングロットを確保すること パーキングロットとは: 議論する際に、今すぐ話し合うべきではないと判断される話題などを一旦保留しておくために、机やホワイトボードの隅などに設けられるスペースのこと。 ▷▷▷会議が終わった後に、話したい議題について必要なメンバーだけ集まって話す流れのこととして定義しています! 私の場合によくパーキングロットで話す内容が、 モバイルアプリ開発における技術的な質問 使用するツール 細かい話 コミットメッセージの規則 タスク要件の再定義など など、たくさんありました!中でも技術的な質問が一番話していましたね😌 会議が終わった後に、個別でパーキングロットを開きます。話したい人は話して、聞く必要がある人は聞くイメージですね。 これができていれば、、、 ■議論の混乱や、無駄な議論を避けることができる! ■話を聞かなくても良いメンバーの時間を奪うことがない! 【4】変化があったものは記録を残すこと(その場で) イメージは、議事録という「誰に見せても分かるようなテキスト」ではなく、「話した内容が思い出せる粒度のメモ書き」みたいなものを想像してもらえると嬉しいです!! それを、会議の最中に書いてしまいます!会議後ではなくです! これができていれば、、、 ■メンバー間で共通認識が常に取れる! →専門的な話でも、言語化して記録されているので、どのような内容かはざっくり把握できる ■後から証拠として出せる! →相手の認識に齟齬がある場合に、メモを見せれば即解決! ■図や画像なども乗せることができて、イメージしやすい! →これも口頭で説明するより図で説明したほうが圧倒的にすぐ終わる ※記録がないと、後から再度聞くという二度手間になりますし、見返したい!と思った時に見れない、図が合ったほうが良い時に分からない、という最悪なことになります😇新卒研修の際にも可視化することの重要性を知りました。 【5】認識の齟齬がなくなるまで会議を終わらせないこと これは、曖昧な理解のままで会議を退出するなあああああ!!!!って意味ですね😇 チームでやることというより、 個人で 意識してやっておくと良いことになります。 分からない、と思ったまま退出するのが、自分にとってもチームにとっても危険です、、 ちょっとした疑問でも、その会議中で質問して解消するまで行うとGoodかなと、個人的には思ってます! これができていないと、、、💦 ■自分がこれから何をするのか分からない状況に陥ってしまう、、 →会議終了後にすぐ動ける状態になっていないのは、自分が一番困ってしまいます!席に座ったら何をしたらいいか想像できるくらいまで、理解の粒度を細かくしましょう〜! ■後から分からない点を聞くはめに、、 →自分のも、相手の時間も奪ってしまいメリットありません!(手戻りってやつですね)わかってはいるものの実行に移すのが難しいのですが😇 【※】開催頻度は毎朝☀️ これは、自分がプロジェクトを進めるにあたってスムーズに進められている要因の一つでもあ ったので書きました! 毎朝開催すると、、 ■プロジェクトの進行状況が1日置きで分かる! →何が進んで何が進んでいないかが明確! ■手元にきた重要な情報もすぐ共有できる! →共通認識がとりやすい! ■分からないことがあれば、直接聞ける! →テキストで聞くより圧倒的に早いから工数削減につながる 逆に毎朝開催しなかった時に一番困ったことは、自分目線、「分からないことを聞くこと」でした。 技術的な質問なんて、細かいところを文章で書き起こさないといけない場面がいくつもありました。 それを長文で返して、長文で返ってくる、それをまた長文で返す、みたいな繰り返しで ほぼ1日経ってるやんけえええ!! って思った日もあります。 毎朝であれば質問があれば聞く機会が既に設けられているので、心理的安全性もありますし、聞きたいことがない日はそれでOKなので非常に助かっています! 最後に。 以上です! (書いた内容がMECEにそってないかもしれませんが、追々意識します、!) 見返すと、意外と当たり前なことやな🥱って思った方も多いかもしれません! ただベンダーさん会議とは別で、社内の会議にいざ参戦!してみると、そんなこともなく、バラバラでした。 「会議」って一言で表せるけど、かなり奥深くて大変ですね😇 ベンダーさんもいつまでも契約が続くわけではないので、この当たり前は自分の中でも維持して、プロジェクトをスムーズに進めていきたいな!と思ってます! ※余談ですが、この間ちょうど社内の会議やコミュニケーションの最適化について議論する場に参戦したのですが、少し似たような話も上がってたので、少しは考え方が共通しているのではないかと思いましたっ 閲覧いただきありがとうございました〜!🥰
はじめに 本日12月15日は C++14 (ISO/IEC 14882:2014) と C++20 (ISO/IEC 14882:2020) のリリース日です。 C++14 は8年前の2014年12月15日、C++20 は2年前の2020年12月15日 にリリースされました。 C言語といえば、先日(2022/11/19)に「人間Cコンパイラコンテスト」に参加し、ランキング1位を獲得することができました。このエントリーでは人間Cコンパイラのはじめかたをまとめていきます。 人間Cコンパイラコンテストとは? 「人間Cコンパイラコンテスト」(HCCC)とは競技者自身がCコンパイラとなり C言語からアセンブリを生成し、その時間と正確さを競う競技です。日本ネットワークセキュリティ協会(JNSA) の SECCON実行委員会が実施する「SECCONCON」内で第一回大会が開催されました。 HCCC / 人間C言語コンパイラコンテスト 詳しくは、以下の 公式説明スライド を参照ください。 この大会ではチュートリアル問題も含めて全20問が出題されています。単純に数字を戻り値として返す問題から、四則演算、ローカル変数利用、文字列処理、ハローワールド、Fizzbuzzなど典型的なプログラムが多く出題されました。 人間C言語コンパイラコンテスト Problems チュートリアル チュートリアル問題 チュートリアル問題を解いていきましょう。実際に一問目として出題された 究極の疑問の答えを返すプログラム を題材とします。 //return_42.cint main(void) { return 42;} 開発環境の構築 これくらい単純なプログラムであればそのままポータルサイトに入力しても問題ありませんが、複雑なプログラムではローカル環境でのデバッグが必須です。ここでは公式が提供している検証環境を利用して開発環境を構築します。 ~$ git clone https://github.com/HumanCCompilerContest/HCCC_local_env~$ cd HCCC_local_env~/HCCC_local_env$ docker build -t hccc_local_env .~/HCCC_local_env$ docker run -it --rm hccc_local_env アセンブリコードの作成 開発環境では vim や emacs などコーディングエディタが利用できます。 ここでは、vim を利用して ファイル return_42.s を新規作成し、先のC言語のソースファイルをx86_64アークテクチャのアセンブリに変換してコーディングしていきます。 root@a741545b3735 ~$ vim hccc/return_42.s ▼return_42.s .globl mainmain: push %rbp mov %rsp, %rbp mov $42, %rax mov %rbp, %rsp pop %rbp ret アセンブルと実行 開発環境では アセンブリコードのアセンブル&実行するコマンド「asm2bin」 が用意されています。 作成したアセンブリコードファイルを引数にして実行します。 root@a741545b3735 ~$ asm2bin hccc/return_42.s 実行後、返り値として「42」が返っていることが確認できました。 root@a741545b3735 ~$ echo $?42 デバッグ 開発環境では PEDA 拡張された gdb が利用できます。 asm2bin 実行すると、実行オブジェクトファイルはカレントディレクトに「tmp」として保存されていますので、これをデバッグ実行します。 $ gdb tmp$ break main$ run 命令ポインタ前後の命令やレジスタ値、スタックフレームなどが可視化させれているため、効率的なデバッグが可能です。 人間コンパイルの知識リソース C言語からx86_64アセンブリにコンパイルするためには、C言語(C99)、CPU命令(x86_64)、ABI (System V Application Binary Interface)、アセンブラ疑似命令に知識が必要です。 以下、参考になるインターネットリソースを記載します。 (※競技中はレギュレーションで認められたもののみ閲覧可能です) 公式リソース 公式レポジトリ 公式チュートリアル C99 System V Application Binary Interface AMD64 Architecture Processor Supplement その他のリソース x86 Assembly Language Reference Manual : Assembler Directives AMD64 ABI の特徴 低レイヤを知りたい人のためのCコンパイラ作成入門
はじめに マイナビでは、一部のシステム職員に向けてDaaS環境を提供しており、サービスには「Azure Virtual Desktop」を採用しております。 Microsoft社が提供するAzure Virtual Desktopはなんと Windows 10 Enterprise Microdsoft 365 Business Premium以上 のライセンスがあれば、追加ライセンスは不要で利用が可能なDaaSとなっています。 加えて、Azure AD P1以上があれば条件付きアクセスによる詳細なアクセスコントロールもできます。 今回は、そのAzure Virtual Desktopを構築し利用できるまでの道のりと共に、メリットデメリットを含めて共有できればと思います。 Azure Virtual Desktopサービスとは? Microsoftが提供するクラウド型のDaaS(Desktop as a Service)は、実は2種類存在しています。 1. Windows 365 決められたプラン(スペック)の中から利用ができる、シンプルな構成のDaaS。 利用者数が少ない、利用要件が少ない…など「とりあえずDaaSが使いたい」環境向けサービス。 24H365Dで稼働しっぱなしのため、ランニングコストは安くない。 2. Azure Virtual Desktop 様々なカスタマイズ、利用方法を提供する上位のDaaS。 1台を複数人で利用できる「マルチセッション」や、細かなポリシーカスタマイズが可能。 利用状況に応じて自動シャットダウンも可能なため、費用をコントロール出来ます。 ある程度の数を展開する場合や、要件が明確な場合はこちらをオススメします。 Azure Virtual Desktopの構成を理解しよう Azure Virtual Desktop(以下、AVD)は、既存のVDIシステムと似ている部分が多々あります。 構築をしてみる前に、まずはどのような要素から成り立っているかを把握しましょう。 引用元: エンタープライズ向け Azure Virtual Desktop - 主要な論理コンポーネント間のリレーションシップ AVDは大きく、 コントロールプレーンと呼ばれる管理環境 ホストマシンやプロファイルの仮想デスクトップ実行環境 2つに分けられます。 コントロールプレーンはMicrosoft社の管理下にあるため、利用側での設定や運用は不要です。実際に、設定や運用管理が必要なのは仮想デスクトップを実行するための環境だけですね。オンプレでVDI環境を運用する場合、管理環境の維持だけでも大変なのでこれはありがたいですね。 また、ある程度の規模間の企業様であればExpressRouteを既にご利用の場合もあるかと思います。 オンプレ~Azure間を閉域でつなぐ場合はこちらも利用しましょう。 過去、AVDを利用するにはAD+AADのハイブリッド構成が必須でしたが、現在では、AADのみの環境もサポートされています。 ただし、一般的にはハイブリッド構成を利用している環境の方が多いと思いますので、今回は仮想マシンをオンプレADに参加させる方式で説明いたします。 構築をしてみよう ここまで概要を説明いたしましたが、ここからは実際にAVDを構築し仮想デスクトップを利用してみましょう。 まず、今回の前提条件としては下記構成で構築に臨みたいと思います。 ・ExpressRouteを利用し、オンプレとの相互通信が可能である・オンプレ上にActive Directoryが存在している・オンプレ上にAzure AD Connectが存在している(AD⇔AADが同期済みである) ①リソースグループを作る Azure上に作成される各コンポーネントを取りまとめるため「リソースグループ」を作成します。 リージョンは「東日本」か「西日本」のどちらかを選択しましょう。 ②仮想ネットワーク(VNET)を作る AVD環境で仮想マシンがドメインに参加できるように、オンプレADの名前解決が可能なサーバをDNSに指定しましょう。 ADサーバがDNSを兼ねている場合は、ADサーバを指定してあげると良いでしょう。 そのほか、仮想ネットワークではサブネットの設定も可能となっています。 ネットワークの環境や要件に応じて設定を行ってください。 ③マスターイメージの作成 FAT・VDIともに展開ではおなじみのマスターイメージを作成していきます。 このマスターイメージを元に、仮想マシンを展開していきます。 まずは、マスターイメージとなるAzureVMを作成しましょう。 AVD固有機能である「マルチセッション」を使う場合は、イメージを「Multi-session VM」から展開しましょう。 シングルセッションの場合は、Windows10であれば特に指定はありません。 展開後は、通常のWindowsマスタと同様にOSにカスタマイズを施していきます。 ※AzureVMのWindows 10は英語がデフォルトのため、日本語化が必要な場合はOSで設定変更がマストです。 マスターイメージである程度カスタマイズが完了したら、sysprepを行います。 AVDのsysprepでは、応答ファイルがサポートされていません。 弊社で検証した限り、応答ファイルを利用すると展開に失敗します。 そのため、プロファイルのコピーが応答ファイルで実施できません。 応答ファイルを使わないプロファイルコピー設定を事前に行うことで実現は可能です。 ※AVDのサポート対象外となる可能性が高いため、本記事では言及致しません。 sysprepまで完了したら、Azure上でイメージ化するために「キャプチャ」を行いましょう。 これでマスターイメージの完成です。 ③ホストグループの作成 ここまで来たら、あと一歩です。 AVD上の仮想マシンを束ねる「ホストグループ」を作成しましょう。 マルチセッションの仮想マシンの場合は「プール」を選択します。 「個人用」を選択した場合は、仮想マシンと利用者は1:1になります。 ホストプールを作るタイミングで、同時にAVDで利用する仮想マシンも作成することができます。 先ほど作ったマスターイメージから仮想マシンを展開するために「全てのイメージを表示」を選択しましょう。 「マイアイテム」を確認することで、キャプチャしたマスタイメージを選択できます。 あとはドメイン参加するための情報や仮想ネットワークの設定やらを入れてあげれば完成です。 初回作成の場合は、ワークスペースもここで一緒に作成すると展開が楽です。 無事展開が完了すると、ホストプールに仮想マシンが作成されます。 最後に、仮想マシンを利用できるユーザを設定してあげます。 シングルセッションの場合は前述の通り1:1ですが、マルチセッションでは複数人設定が可能です。 シングルセッションの場合↓ マルチセッションの場合↓ 接続してみよう ここまでの準備ができたら、いよいよ接続が可能になります。 AVDには2種類の接続方法があり、 ブラウザからのアクセス 専用RDPアプリからのアクセス が可能です。 ただし、ブラウザからのアクセスはレスポンスが悪いのでオススメしません。 今回は専用アプリから接続してみます。 専用アプリにAzureADアカウントでサインインをすると、割り当てを行った仮想マシンが表示されていますね。 選択してみるとこのように仮想マシンに接続ができます。簡単ですね!!!! ※オンプレADとAADのハイブリッド環境の場合、展開時に自動的にAD参加を行ってくれます。 そのため仮想マシン自体へのログインにはオンプレADアカウントを利用します。 運用編 ここまでで、なんとなく作り方や使い方のイメージが付いたかと思います。 ただし実際には、もう少し作りこみが必要です。 例えば、 このサービスは従量課金制です。 そのため、仮想マシンは使った分だけ課金され続けます。 ここで重要なのは「シャットダウン」だけでは課金され続けてしまいます。 停止 (割り当て解除) は、仮想マシンが稼働する物理ホスト サーバーから割り当てられているリソースの割り当てを解除する操作であり、起動は物理ホストサーバーからリソースを割り当てる操作です。 再デプロイと異なり、明示的に別の物理ホスト サーバーでデプロイを行うための手段ではありませんが、起動によって仮想マシンがデプロイされる物理ホストサーバーは前回と異なる場合がほとんどになります。 停止 (割り当て解除) では、仮想マシンとしての課金はかかりません。(※ ディスクの課金はかかります。) 引用元: Azure 仮想マシンにおける操作 (再起動、停止/起動、再デプロイ、再適用) について つまりは、仮想マシン側でシャットダウンをしたところで、 Azure側で割り当てを解除しなければ課金され続ける ということですね。 幸い、Azure Virtual Desktopには「スケジュールに応じて自動的に割り当てを解除する」仕組みがあります。 利用時間が決まっている環境であればこの実装だけで費用を抑えられます。 ただし、スケジュール外のメンテナンスで使っている場合などで、急に割り当てが解除されると困りますよね。 そういった場合は、仮想マシンへのセッション有無を定期的にAzure側で判断し自動で割り当てを解除する仕組みを導入する必要があります。 合わせて、 ARMテンプレートを利用しない場合ホスト名の規則に融通が利きません。 この二つの実装は、インターネット上に先駆者の情報がありますので、参考にしてみてください。 まとめ AD・AADのハイブリッド環境かつ物理リソースを持たないVDI という点は非常に魅力的です。 ただし、細かいカスタマイズが難しいのは否めません。このあたりは「Citrix with AVD」や「Horizon Cloud with AVD」を活用すると、オンプレVDIと同じ感覚で運用ができるかもしれません。 とはいえ、弊社環境では社員用のFAT PCと同様のカスタマイズが実現できていますし、本番運用環境は一人で構築しています。 元々Azureに知見がある、マスタ展開の経験がある、VDI構築に携わったことがあるなど、なんらかの条件があれば、抵抗なく構築運用が可能かと思われます。 PCの持ち出しができない環境がある場合、このDaaSの仕組みは非常に魅力的かと思います。既にM365の該当ライセンスをお持ちの方は、是非活用してみてはいかがでしょうか。
はじめに マイナビではマネージドなWordPress基盤「SMEW」が社内向けに提供されており、WordPressを使ったサイトの多くがSMEW上で稼働しています。 ご存知の通り、WordPressは多くの脆弱性が報告されます。脆弱性に迅速に対応できるよう、WPScanとElastic Stackを使って、SMEW上で稼働している各サイトのWordPress脆弱性を自動でスキャンするシステムを開発しました。本記事で簡単に紹介します。 ▼SMEWについての詳細はこちらをご覧ください ###card_post_id=1249### WPScanとは オープンソースのWordPressの脆弱性スキャンツールです。 WPScanを利用してみる WPScanは Kali Linux に標準で入っています。 wpscan --url "https://hogehoge/" --api-token "{token}" -format json オプション url サイトのURL api-token WPScanにユーザ登録した時に発行されるトークン format 出力結果のフォーマット 実行結果(一部抜粋) スキャン結果の「vulnerabilities」のフィールドに、脆弱性名、CVE、Fixのバージョン等の詳細情報が出力されます。 下記、スキャン結果から、All in One SEO Packというプラグインに脆弱性があることがわかります。 ▼スキャン結果 { "main_theme": null, "plugins": { "all-in-one-seo-pack": { "confidence": 30, "confirmed_by": {}, "directory_listing": null, "error_log_url": null, "found_by": "Comment (Passive Detection)", "interesting_entries": [], "last_updated": "2022-03-30T17:01:00.000Z", "latest_version": "4.1.9.4", "location": "https://hogehoge/webroot/plugins/all-in-one-seo-pack/", "outdated": true, "readme_url": null, "slug": "all-in-one-seo-pack", "version": { "confidence": 60, "confirmed_by": {}, "found_by": "Comment (Passive Detection)", "interesting_entries": [ "https://hogehoge/, Match: 'All in One SEO Pack 2.6.1 by'" ], "number": "2.6.1" }, "vulnerabilities": [ { "fixed_in": "3.6.2", "references": { "cve": [ "2020-35946" ], "url": [ "https://www.wordfence.com/blog/2020/07/2-million-users-affected-by-vulnerability-in-all-in-one-seo-pack/" ], "wpvulndb": [ "528fff6c-54fe-4812-9b08-8c4e47350c83" ], "youtube": [ "https://www.youtube.com/watch?v=2fqMM6HRV5s" ] }, "title": "All in One SEO Pack < 3.6.2 - Authenticated Stored Cross-Site Scripting" } ] } }, "requests_done": 186, "start_memory": 52584448, "start_time": 1648701772, "stop_time": 1648701796, "target_ip": "198.51.100.0", "target_url": "https://hogehoge/", "used_memory": 219262976, "used_memory_humanised": "209.105 MB" -略-} Elastic Stackとは Elasticsearch、Kibana、Beats、Logstashの総称。 ログをリアルタイムに検索、分析、可視化することができます。 Kibanaのアラート機能を利用して、特定の条件のログがあったら、SLACK等に通知できます。 自動化の取り組み 処理の流れ SMEW上で管理されたサイト一覧を取得し、DynamoDBに格納する。 スキャン対象キューに入れる ECSTaskを起動し、スキャンを実行する。 脆弱性があるログを検知したら、Slackに通知する。 構成図 通知結果(例) まとめ 今後もSMEWだけでなく、マイナビの全てのサイトのセキュリティを高めるための技術開発に取り組んでいきます。
はじめに こんにちは。AIシステム部のS.Tです。 AIモデルを作るための学習環境といえば、JupyterNotebookを思い浮かべる方も多いと思います。セルにコードを書き、順次実行して結果を確認しながらコーディングを進めることができるので、研究開発には持ってこいのツールとなっています。 ただ、AIに関する業務となると、AIモデルの学習のあと、そのAIモデルの予測結果を、自社のサービスや業務改善に活用するフローを運用するところまでがセットとなります。ビジネス的なニーズによって、定期バッチで実行したり、モデルの予測機能をサーバアプリとして提供する場合もあります。これを行う場合、JupyterNotebookでは少々やりにくいかな、と思います。 Vertex AI Training で、こういったニーズを解決するために、Google Cloud Platform(以降GCP)では、 Vertex AI というAIに特化したプロダクトが開発されております。そのサブプロダクトである Vertex AI Training を用いると、GCPのマネージドな環境で、学習やハイパーパラメータチューニングを行ったり、そのモデルの予測提供するための環境も比較的簡単に作れます。 Vertex AI Trainingでは、 AutoML という、コーディングをせずとも学習ができる方法と、 カスタムトレーニング という、自前でプログラムを用意して学習を実行する方法がサポートされております。今回は、Dockerコンテナを使った カスタムトレーニング の方法を行ってみます。 今回使用する学習タスク 今回は、サンプルですので、機械学習のHelloWorldとも言える、アイリスデータの分類に挑戦してみましょう。モデルは、サポートベクターマシンによる分類器を試してみます。 (あ、ちなみに著者はあまり機械学習モデルの詳しい仕組みについては詳しくないのであしからず。。) データ BigQueryの iris_data というデータセットに iris_table というテーブルを用意しました。列名はこんな感じです。 列名 型 説明 sepal_length___cm__ FLOAT がくの長さ sepal_width___cm__ FLOAT がくの幅 petal_length___cm__ FLOAT 花びらの長さ petal_width___cm__ FLOAT 花びらの幅 label (今回の予測対象) INT アヤメの種類(0, 1, 2) 学習コードを書く ディレクトリ配置 ディレクトリ配置は最終的に以下のようになります。 .├── custom_training│ ├── Dockerfile│ ├── Pipfile # 環境構築用│ ├── Pipfile.lock # 環境構築用│ └── src # 学習用ソースコード│ └── train.py└── docker-compose.yml 環境構築 まずは、 custom_training というディレクトリを作ります。その中に、 src というフォルダを作ります。 mkdir custom_training && cd $_mkdir src いま、 custom_training ディレクトリにいますので、ここで pipenv による環境構築。 pipenv install scikit-learn google-cloud-bigquery pandas click すると、こんな感じになります。 .└── custom_training ├── Pipfile ├── Pipfile.lock └── src では、srcのなかに train.py を作成して、学習コードを書きます。 (以降、GCPプロジェクト名は <YOUR_PROJECT_ID> で伏せています) from __future__ import annotationsimport osimport pickleimport refrom dataclasses import dataclassfrom typing import Unionimport clickfrom google.cloud import bigqueryfrom sklearn.svm import LinearSVCfrom sklearn.model_selection import train_test_split# Vertex AI Trainingの場合は、実際に学習が実行されるGCPプロジェクトIDが# CLOUD_ML_PROJECT_IDという環境変数に格納されるif os.getenv('CLOUD_ML_PROJECT_ID'): client = bigquery.Client(project=os.getenv('CLOUD_ML_PROJECT_ID'))else: client = bigquery.Client()@dataclassclass GCSPath(): bucket: str key: str @classmethod def get_fuse_directory_path_from_gcs_uri(cls, gcs_uri) -> str: """ GCSのURLを受け取って、その場所をCloud Storage FUSE経由で見るためのパスを返す。 """ gcspath = cls.get_gcspath_from_gcs_uri(gcs_uri) return f"/gcs/{gcspath.bucket}/{gcspath.key}" @classmethod def get_gcspath_from_gcs_uri(cls, gcs_uri) -> GCSPath: """ GCSのURL表記からバケット名とキー名を抽出して、GCSPathオブジェクトにして返す """ pattern = "gs://(?P<bucket>[^/]+)/(?P<key>.+)" m = re.match(pattern, gcs_uri) if m: bucket = m.group("bucket") key = m.group("key") return cls(bucket=bucket, key=key) else: raise ValueError(f"{pattern} is invalid GCS URI.")def get_gcsfuse_model_save_dir() -> Union[str, None]: """ GCS上にモデルを保存する用のディレクトリを取得。 Vertex AI Training上で実行していない場合はNoneを返す。 Returns: Union[str, None]: GCS上にモデルを保存する用のディレクトリ。 Vertex AI Training上で実行していない場合はNoneを返す。 Note: Vertex AI Trainingで実行するとき、 自動的に環境変数AIP_MODEL_DIRにモデルの保存先のGCSのURLが渡される。 """ model_save_dir = os.getenv("AIP_MODEL_DIR") if model_save_dir: return GCSPath.get_fuse_directory_path_from_gcs_uri(model_save_dir)def get_training_data(): """学習データをDataFrameで取得する""" df = client.query('SELECT * FROM `<YOUR_PROJECT_ID>.iris_data.iris_table`').to_dataframe() return dfx_col = [ "sepal_length__cm_", "sepal_width__cm_", "petal_length__cm_", "petal_width__cm_"]y_col = "label"@click.command()@click.option("--model-save-dir", type=str, help="学習モデルの保存先")def train(model_save_dir: Union[str, None] = None): """ 学習を実行し、モデルを保存する。 Args: model_save_dir (Union[str, None], optional): ローカル環境で実行するときは指定が必要である。 Vertex AI Trainingで実行するときは指定は不要。 """ # モデルを作成 model = LinearSVC() # 学習データを取得する train_data = get_training_data() X, y = train_data[x_col], train_data[y_col].tolist() X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # いざ、学習! model.fit(X_train, y_train) # モデルの保存先を取得する。 # Vertex AI Trainingで学習している場合はGCS Fuseでアクセス可能なディレクトリが # ローカル実行の場合は、引数のmodel_save_dirが使用される。 model_save_dir = get_gcsfuse_model_save_dir() or model_save_dir if not model_save_dir: raise ValueError("モデルの保存先が設定されていません。") # モデルを保存する if not os.path.exists(model_save_dir): os.makedirs(model_save_dir) model_save_path = f"{model_save_dir}/model.p" with open(model_save_path, "wb") as fp: pickle.dump(model, fp)if __name__ == "__main__": train() ためしに動かしてみます。 # BigQueryのテーブルが存在するプロジェクトをデフォルトプロジェクトにするgcloud config set project <YOUR_PROJECT_ID># 学習を実行するpipenv run python src/train.py --model-save-dir $(pwd) 学習が実行されて model.p というファイルが生成されました。 Dockerイメージを作る 今回はカスタムコンテナを使ってVertex AI Trainingで学習しますので、Dockerイメージを作成します。 custom_training/ ディレクトリ内に Dockerfile を作ります。 FROM python:3.9.6COPY ./Pipfile.lock /app/COPY ./src /app/srcWORKDIR /appRUN pip install pipenvRUN pipenv sync# ENTRYPOINTで学習実行スクリプトが開始するようにする!ENTRYPOINT pipenv run python src/train.py docker-compose.yml を、 custom_training の親ディレクトリに作ります。 services: backend: image: vertex-custom-training/iris_data build: context: ./custom_training ビルド docker compose build リポジトリにプッシュ Vertex AI Trainingから見える位置(GCP環境上か、Docker Hub)に、Dockerイメージをプッシュしましょう。 今回はGCP内のプライベートなコンテナレジストリであるGoogle Container Registry(GCR)にプッシュします。 # GCRの認証ヘルパーを設定。gcr.ioに認証できるようになるgcloud auth configure-docker# あとはpushするdocker tag vertex-custom-training/iris_data:latest gcr.io/<YOUR_PROJECT_ID>/vertex-custom-training/iris_data:latestdocker push gcr.io/<YOUR_PROJECT_ID>/vertex-custom-training/iris_data:latest Vertex AI Trainingで実行する 手元環境用に、 google-cloud-aiplatform をインストールします。 pipenv install --dev google-cloud-aiplatform custom_training 内に、 submit-training-job.py を作成します。 from google.cloud import aiplatformdisplay_name = "verify-vertex-ai-training-iris"# さっき作ったDockerイメージのURLimage_uri = "gcr.io/<YOUR_PROJECT_ID>/vertex-custom-training/iris_data:latest"# ステージング(モデルを置いたりチェックポイントをおくところ)用のバケットを1つ作るstaging_bucket = "gs://<YOUR_BUCKET_NAME>/verify-vertex-ai-training-iris/staging"custom_job = aiplatform.CustomContainerTrainingJob( display_name=display_name, container_uri=image_uri, staging_bucket=staging_bucket)custom_job.run( machine_type="e2-standard-4") このスクリプトを実行すると、Vertex AI Training上で学習が実行できます。 pipenv run submit-training-job.py 学習が完了すると、 submit-training-job.py 内で変数 staging_bucket に設定したGCSの場所に、モデルが保存されていると思います。 感想とまとめ 今回は普通にモデル学習のみを行う部分を作ってみました。 アイリスデータのような小さなデータであれば、デスクトップ上でも実行できてしまいますが、実際もっと大きなデータを扱う場合は、もっと大きな計算リソースが必要になる場合もあります。 大きな計算リソースでNotebookを手動で実行することもできますが、Vertex AI Trainingのようなマネージド学習環境を使うと、学習が終わると使われた計算リソースが勝手に落ちるので、安心だしコスト効率もいいと思います。 また、すごーく長くなりそうなので今回は触れなかったのですが、分散処理やハイパーパラメータチューニングも、コスト効率よく実行できたり、予測サービスとして提供する場合のコンテナも簡単に作れるので、機会があればやってみたいと思います。 ※サムネ画像で利用しているロゴはVertex AI Trainingより引用
はじめに この記事は、自分が効率化をしていくうえでGASを用いたので、GASの使い方を載せたものです。 今回の内容としては、スプシの内容を整形してTeamsに通知するというものになります。 準備 まず、GASで整形した内容をTeamsに送るために準備が必要になります。 まずは、Teams上にチャネルを用意します。 用意したら、三点リーダーからコネクトを選択し、Incoming WebHooksをクリックします。 Incoming WebHooksのセットアップを作成すると、URLが発行されるので、大切にとっておきましょう。 これで準備は終わりです。 内容 まずは、Teamsに内容を送る関数notificationを作成します。 function notification(title,completetext){ var payload = { 'title' : title , //投稿の題名 'text' : completetext //投稿の本文 }; var options = { 'method' : 'post', 'contentType' : 'application/json', 'payload' : JSON.stringify(payload), // jsの値をJSON文字列に変換する }; var url = 'URL'; //さきほど大切にとっておいたURLを記入 UrlFetchApp.fetch(url, options); //送る } 上記のコードを簡単に説明すると、通知する内容をTeamsに適切に表示し、通知できるようにするコードです。 コード内にある、title,textについては次の関数で中身を入れます。 次に、スプシの内容を読みこみ、内容をTeams上で表示できるようにするgetmessage関数を作成します。 function getmessage(content){ console.log(JSON.stringify(content)); //メッセージを表示させる//スプシ関連 var ss = SpreadsheetApp.openById("フォルダID");//スプシのフォルダIDを入力 var sheet = ss.getSheetByName('通知内容'); //読み込むスプシ var range = sheet.getDataRange(); //全範囲を指定 var values = range.getValues();//データ取得 ①上記のコードのSpreadsheetApp.openByIdの後にスプシのフォルダIDをいれます。 ②getSheetByNameの後にはシート名をいれます。 では、内容の作成にいきます。 今回はスプシにある内容から明日の予定を抽出し、出力する内容にします。 //日付関連 var date = new Date(); //現在の日本の日付を取得 var onedate = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1); //1日後にする var twodate = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 2); //2日後にする//タイトル var title = '明日の予定'//本文 var row = sheet.getLastRow(); //最終行の取得 var text = ''; for (var i=1; i<row; i++){ var text1 = ''; if(values[i][0] >= onedate && values[i][0] < twodate){ text1 = text1 + '\n\n<br><u>**' + '・名前:'+ values[i][1] + '**</u>'; text1 = text1 + '\n\n・時間:' + values[i][3]; text1 = text1 + '\n\n・内容:' + '**'+values[i][2] + '**'; text = text + text1; } } if(text == ''){ text = '明日の予定はありません' } notification(title,text);} Teamsに通知がきました。 おわりに 今回は簡単な出力にしましたが、もっとたくさん活用できます。 また、私自身もまだまだ初心者なのでより便利に使いこなせるように精進してまいります。
はじめに 私の所属するサイバーセキュリティ課では、マイナビグループの事業発展をサイバーセキュリティで支えるべく、日々業務に励んでいます。 サイバーセキュリティに関することは何でもやる!という部署で、主に以下のような業務に取り組んでいます。 セキュリティモニタリング セキュリティエンジニアリング セキュリティポリシーや制度の立案・運用 システム企画、設計のレビュー システム実装、運用の支援 インシデントハンドリング サイバーセキュリティに関する情報収集と提供 セキュリティ教育、訓練 現在、私は脆弱性関連を担当しており、脆弱性診断の内製化に取り組んでいます。 本記事では、脆弱性診断の内製化(内製診断)にあたり準備したことをまとめました。 なぜ内製化? マイナビでは、規模の異なる多数のWebサイトを管理しています。 定期的な脆弱性診断を実施するにも、すべてを外部業者に依頼するには、時間もコストもかかりすぎてしまいます。 そこで、一部Webサイトでの脆弱性診断を内製化することで、タイムリーかつコストパフォーマンスよく実施できると考えました。 準備すること 診断方法やツールを選定する 診断すべき脆弱性項目を一覧化する 脆弱性の評価基準を決定する ユーザーからの申請方法を決定する 1. 診断方法やツールを選定する どのように診断を行なうのかを決めます。 ツールを用いた自動診断だけなのか、手動診断も行なうのか、ツールは何を使うのか・・などです。 診断ツールは、無償で利用できるものもあります。「OWASP ZAP」や「Burp Suite」が有名です。 OWASP ZAPを試してみる OWASP ZAPは、オープンソースの脆弱性診断ツールです。 ナレッジが多く、導入が簡単なため、まずはこちらを試してみることにしました。 ソフトウェアのインストール 以下のソフトウェアをインストールします。 OWASP ZAP Java Firefox(診断時に利用するブラウザ) 各種設定 OWASP ZAPのローカルプロキシ機能を設定します。 OWASP ZAPを起動し、歯車マークからローカルプロキシの設定を開きます。 デフォルトでは localhost:8080 となっていますが、必要に応じて変更します。 診断時に利用するブラウザを開き、OWASP ZAPのローカルプロキシの値を設定します。 Firefoxの場合は「FoxyProxy Standard」という拡張機能が便利です。 スキャン実行 ※第三者のWebサイトに、勝手に脆弱性診断を行うと攻撃とみなされます。診断を行なう際は、自身で管理しているWebサイトに限ってください。 プロキシを設定したブラウザ(Firefox)から診断対象にアクセスすると、OWASP ZAPの左ペインにWebサイトのURLが追加されます。 OWASP ZAPには、4つのモードがあります。 「攻撃モード」「標準モード」は、対象外のWebサイトへも診断を行なってしまう可能性があるため、「プロテクトモード」でのスキャン実行がおすすめです。「セーフモード」ではスキャンが行なえません。 「プロテクトモード」では、診断対象をコンテキストに含めることでスキャンが可能になります。 診断対象のURLを右クリックし、「攻撃」を選択するとスキャンが実行されます。 スキャンは、「スパイダー」と「動的スキャン」の2つがあります。 スパイダー 診断対象に存在するURLを洗い出し、レスポンスの内容などを検査します 動的スキャン リクエストパラメータを変えるなどして検査をします レポート生成 メニューバーの「レポート」から診断結果を生成することができます。 HTMLやPDFなど形式を選択できます。 2. 診断すべき脆弱性項目を一覧化する IPAや脆弱性診断士スキルマッププロジェクトなどで、一覧化された脆弱性項目が公開されています。 マイナビでは、 OWASP ASVSなどを参考に策定したセキュリティチェックシートが存在するため、これらを掛け合わせて診断すべき項目を一覧化しました。 実際に診断を行なう際は、対象サイトの仕様に応じて診断すべき項目を精査します。 3. 脆弱性の評価基準を決定する 発見された脆弱性が、どの程度影響のあるものなのかを評価するための基準を決めます。 高・中・低・情報レベルで分けることが多いかと思います。 マイナビでは単に脆弱性自体の危険性だけでなく、SSVCを用いて実際の影響度を考慮し判断することにしました。 SSVCは、判断ポイントがわかりやすく、ユーザーにも説明がしやすいという点で採用しました。 SSVCとは? 脆弱性を対応する基準として、多くの場合はCVSSのベーススコアや深刻度を用いますが、 これは「脆弱性自体の危険性」を表しており、対応の優先順位付けを行なうには情報が不十分です。 実際の影響度は、システムが置かれている環境や扱っている情報の重要度により変わってきます。 SSVCは、この問題を解決するために考案された脆弱性管理のフレームワークです。 以下の4つの情報をインプットとして、4段階の対応レベルを導出します。 情報 攻撃コードの公開有無と悪用レベル 攻撃者にとっての有用性 システムの露出レベル 攻撃された際の業務影響 対応レベル Immediate 全てのリソースを集中し必要に応じて組織の通常業務を停止して可能な限り迅速に対応する Out-of-Cycle 通常よりも迅速に行動し、計画外の機会に緩和策または修復策を実施する Scheduled 定期メンテナンス時に対応する Defer 現時点では対応しない 4. ユーザーからの申請方法を決定する 内製診断を実施したいユーザーからの受付窓口が必要です。 ヒアリングも兼ねて、以下のような項目を入力するフォームを用意しました。 部署名・氏名 サイト名・サイトURL サイトの仕様 プラットフォーム、OS、開発言語、構成など 診断実施希望日 リリース予定日 いつまでに診断を完了する必要があるか確認するためです 注意事項の確認 診断実施にあたり注意事項のページを別途用意しました まとめ 今回は、内製診断をスモールスタートするために準備したことをまとめてみました。 ここに記載したツールの利用方法や評価基準だけでなく、脆弱性に対する理解は必須です。 ユーザーに安心してWebサイトを利用してもらえるように、抜け漏れなくしっかりと診断を実施していきたいと思います。 サイバーセキュリティ課では、様々な施策に取り組んでいます。 脆弱性診断に限らず、さまざまなセキュリティ知識を身に着けるべく自身のスキルアップにも努めてまいります。💪 最後まで読んでいただきありがとうございました!
はじめに こんにちは、IT企画推進部のA.Hです。 IT企画推進部は、デジタルテクノロジー戦略本部内の教育や組織活性を主に担当する部署で、入社した新卒の研修の企画・運営などを担当しています。 例年、マイナビ社に入社したWeb/IT系の新卒は、入社後3か月程度の研修に入りますが、その研修期間中は、研修の最後に日報を提出して一日を締めくくります。 今年からは、新卒研修の日報を管理するシステムとしてRedmineを設定し、提供致しました。 その導入に至った背景、設計の考え方、実際の設定の 雰囲気 などを書いてみようと思います。 (この7つの矩形が何を表すのかはよく分からない。) 導入の背景 さて、一口に日報といっても、会社の業種や規模によって、日報の提出先や確認フローなどは様々かと思います。 そもそも日報管理にシステム?と思う方もいらっしゃるかも知れません。 例えば、チャットツールにチャネルを作り、今日学んだことを新卒が投稿して、それに先輩がコメントやスタンプをつける、という形式でも、十分に日報として成立します。 実際、去年まではチャットやスプレッドシートの活用によって日報活動を行っていました。 現在のマイナビ社はデジタルテクノロジー領域に大変に力を入れており、新卒採用を積極的に行った結果、2022年度は数十名程度のWeb/IT職の新卒が入社することとなりました。 ・・・そうなってくると、ファイルベースでの更新・閲覧は一覧性や可読性、更新検知において段々と窮屈になってきます。 日報は、新卒の学びの定着のための振り返りであると同時に、先輩からのコメントをもらうコミュニケーションの場でもあります。 また、少し考えてみれば、『あるテーマにそって投稿が行われ、関係者が閲覧してコメントを行う』という行動パターン自体は、エンジニアであれば管理ツール・プロジェクト管理ツールの中で、日々実践しているおなじみの行動です。 新卒はWeb/IT職で、先輩達も当然Web/IT職です。 だったらRedmineで良くね? と思い立ったのが、導入の経緯です。 じゃ、なんでRedmineなの?BacklogとかAsanaじゃだめなの? ITSを日報報告に使うなら、まだリテラシーが低い新卒が混乱しないために、通常よくある機能(例えば工数、開始日・終了日とか)を削るような方向になる。 ⇒ツールの自由度が求められる。 新卒は書く人、先輩は読む人。通常の開発のようにメンバーが同じ権限ではなく、ロールが全く異なりやる事も異なる。特に、新卒は出来ることを限定して迷わないようにしたい。⇒運用ルールが極力システムで表現できる。 多分、多少の改善はあれど来年も同じことをやる可能性が高い。構造だけコピーして使いまわしたい。 お金を掛けたくない。何故ならお金を掛けたくないから。 上記の要求に答えるプロダクトは、正直Redmineくらいしか思い当たりません。 多少の予算があれば機能的にはJiraは選択肢になると思いますが、「多くの先輩にみてもらう」という要件と、アカウント課金は相性が悪すぎます。 日報を掲示板の延伸的な感覚で使う分には、運用ルールの徹底がなされればどのようなBTS/ITSでも使えると思いますが、ただでさえ入社して色々な事を詰め込まれる新卒、日々の業務で忙しい会社の先輩達に、ルールを覚えてもらうことを期待するのは酷というものです。 エンドユーザーに提供する機能を削り、統制を提供するという観点においては、やはりRedmineに軍配があがります。この部分において、BacklogやAsanaは最適解ではないと思います。 などと色々と理由を書きましたが、勿論、 新卒の日報管理のためだけにド新規のシステムなんて入れてられない という話もあります。 幸い、別用途で管理者権限を持つRedmine環境を持っているため、日報管理という業務を理解して、それをRedmineの設定に落とし込めれば、ITSで実現できるな、と思えたわけです。 日報管理という業務 端的には、『新卒が日報を書き、先輩や、研修運営チームはそれを確認してコメントする』だけです。 文字に起こせば当たり前のことを書いていますが、少なくともユースケースに登場しそうなアクターが三種類も登場しています。 もう少し具体的に考えてみます。 新卒のやること 新卒は、Web/IT職採用とはいえ、完全なる初心者です。 基本的には何も知らないし、不都合なことをやりうる可能性があることを想定して考慮します。 まず、新卒は自分の書いたチケットは編集できても、他の新卒が書いたチケットは編集できてはいけません。 開発の課題管理であれば、他の人が書いた誤りを訂正出来るので良いですが、今回は新卒研修なので他の人が編集したり、誤って消したりしないようにする必要があります。 また、Redmineは一度削除したチケットを復元する機能は標準では存在しないため、そもそもチケット削除の権限を取り上げる必要があります。 BTS/ITSそのものにも慣れていません。日報記入に関係がない項目は極力画面から消します。 長い目で見ればトラッカーやステータスなどはしっかり教えたい所ですが、今回はそれすらも意識させないように消します。 私達の研修では、先輩役はローテするので新人は自身の先輩を知り得ません。 なので、「担当者」欄も、今はいりません。 一方で、例えばKPTなど必ず入力してほしい項目は記入されて欲しいです。 同期の新卒が書いた日報は、見せることも見せないようにすることも出来ます。 私達は、「良い日報は他の新卒にも真似をしてほしい」と考えているので、見せるようにします。 先輩のやること 先輩は、日報は書きませんので、新規チケットを作成したり、誰かのチケットを編集する必要はありません。 コメント(注記)が出来ればよいです。 運営研修チームのやること 運営管理者は、ふるまいはほとんど先輩と同じですが、万が一に備えてチケットを追加編集する権限は持っておきたいところです。 Redmineの設定への落とし込み 日報管理にまつわることは、何となく伝わりましたでしょうか。 ユースケースを考える時、私はユーザーの行動を起点に機序を想像するんですが、 Redmineのどのあたりの機能でそれを表現するかは、因数分解をするような感じで、あてはめていきます。 Redmineの機能の全体像 まず、Redmineの全体像を簡単にご紹介致します。 界隈では鉄板ですが、JAXAの方がまとめた下記の図をご確認下さい。 引用: https://www.jss.jaxa.jp/about_coda/ Redmineの仕組みは、上図の通り複層的です。 この辺りの仕組みは管理者権限を得てもシステム内で特に説明がないため、割と初見殺しな部分です。 それだけに色々な使い方が出来るのですが、とりあえず一つだけ、太字の部分を覚えて下さい。 上図の「論理的な定義」に含まれるものは、Redmineの環境単位で共通の設定です。 あるプロジェクトAとBで、トラッカーXを使っているとしたら、トラッカーXの修正はプロジェクトAとBに影響を与えます。 新しいRedmine環境なら、自由にトライアンドエラーをすればいいと思います。 既存のRedmine環境においては、必ず先輩の管理者権限の指示やシキタリに従ってください。 プロジェクト全ての設定を一律で変更出来るのは、メリットであると同時に、 下手に触ると、それはもう凄いことが起こります。 慣れないうちはサンドボックスを用意するか、使いまわさずに独自のものでやりましょう。 という訳で、日報を実現するためにRedmineのどこをいじるかを考えながら設定していきます。 ロールの考え方 文字通り、権限をつかさどる機能です。 Redmineのロールの仕組みは、70を超える細かい機能の利用有無をそれぞれチェックして、 ロールに好きな名前をつけることが出来ます。 例えば、新卒のロールを設定する画面はこんな感じです。 新卒は自分の書いたチケットは編集できても、他の新卒が書いたチケットは編集できてはいけません。 上記要件に関連する設定は、この辺りです。 「チケットの編集」なら、誰が書いたチケットでも編集可能ですが、「自分が追加したチケットの編集」は、自分が書いたチケットでなければ編集が出来ない権限です。 (ちなみに、両方適用すると強い方の前者が適用されます。) Redmineは一度削除したチケットを復元する機能は標準では存在しないため、 そもそもチケット削除の権限を取り上げる必要があります。 これもチケットトラッキング周りです。上の図のチケットの削除をオフにします。 Redmineにはゴミ箱による一時退避のような機能はありませんので、基本的にはオフを推奨します(二度目) 今回は新卒・先輩上司・運営と3つの役割が存在していますので、 この3つを設定していくことになります。 試しに、先輩上司のロール設定を見てみましょう。 今回の日報管理には下記の要件がありますので、 先輩は、日報は書きませんので、新規チケットを作成したり、 誰かのチケットを編集する必要はありません。 コメント(注記)が出来ればよいです。 チケットの追加にチェックが入っていません。 おまけ:他の新卒が書いたチケットを見せたくない場合。 日報とは別に、後続課程の新卒向けのインターンシップの報告書については、ネタバレ防止などの観点から他の新卒が書いた日報は見れないように変更しました。 この設定は「表示できるチケット」の項目を「作成者か担当者であるチケット」に設定することで実現します。 ただし、1つのロールでは1通りなため、別のロールとして定義して提供しました。 ロールで出来る事の雰囲気が伝われば幸いです。 トラッカーの考え方 トラッカーは『行動パターンの大分類』です。 今回は新卒からの日報以外の行動パターンはありませんので、トラッカーは「日報」だけがあれば大丈夫です。 トラッカーの設定画面はこんな感じです。 Redmineは、標準フィールドすら使わないことが選べます。 一般的な開発用途であれば、担当者や日付情報などは必須ですが、その日かけば期日もなにもなく、新卒が書いたものを先輩は寄ってたかって読むので担当者も不要。 BTS/ITSそのものにも慣れていません。日報記入に関係がない項目は極力画面から消します。 なので、標準フィールドでは説明だけが残ります。 一方、研修担当としては書いてほしい事は色々ありますので、 カスタムフィールドとして項目を定義します。 今回の研修においては、KPTと自由記入欄を分け、振り返ってほしいことをしっかり入力してもらうようにシステム側で制御をしています。 Redmineは、アカウント情報に事業部や例えば趣味などのカスタムフィールドを拡張することは出来ますが、チケット内に拡張したアカウント情報をLookupするような機能はありません。 なので、新卒は毎回配属事業部を入力しなければならないのでちょっと面倒です。 まぁ書いて覚えることもあるだろうということで。。。 配属事業部やチーム名は、後々一覧画面などで検索する時に必要なため、つけています。 カスタムフィールドの考え方 一方で、例えばKPTなど必ず入力してほしい項目は記入されて欲しいです。 チケットの入力項目のカスタマイズをしたいのであれば、カスタムフィールドです。 先述の通り、トラッカーが定まると、その行動パターンで必ずやってほしいことの土台が何となく見えてきます。 研修日報は、できたこと、できなかったことなど書いてほしいことが明示的です。 帳票項目については、カスタムフィールドを利用することで帳票っぽく仕上げていきます。 例として、Keepの項目のカスタムフィールドはこんな感じです。 一度カスタムフィールドを設定した後、形式を切り替えるは出来ませんが、 こんな感じの選択肢があります。 おまけ:特定の人にしか見せたくないフィールドを作りたい デフォルトでは表示の項目は「すべてのユーザー」が選択されていますが、特定のロールのみ表示するという制御が出来ます。 この部分です。 例えば、社外からの問い合わせに対して、社内でのやりとりを問い合わせしてきた人に見せたくない場合など、同じチケットでも閲覧ロールによって情報を出し分けしたい時などに活用します。 私達の日報管理システムでは特に出番はありませんでしたが、 新卒インターンシップの報告書トラッカーにおいては、メンター⇒管理職と情報を申し送りしたので、その時に活用しました。 ステータスの考え方 ステータスは、チケットの考えうる状態のことです。 例えば、お仕事は「未着手」⇒「対応中」⇒「完了」というフローなのであれば、ステータスはその3つを設定します。 日報にはどういう状態が考えられるでしょうか? まず、新卒の研修が終わった直後、これから日報(のチケット)を書く場合、『未着手』の状態です。 研修日報をすべてチケットとして予めセットするのであれば、 まだ誰も手をつけていない『未着手』という状態ですが、 『研修終了後、15分以内にチケット追加して書いて下さいねー』という場合、 未着手である時間はほとんど存在しないため、『記入済み』という状態から初めてもいいかも知れません。 日報が『記入済み』になったら、先輩上司や運営チームは一定期間の間でチケットを確認してコメントを書きます。 先輩上司と運営チームのどちらが先にコメントを書くか分からないので、一定期間が終了したら、チケットを終了の状態に変更すれば良さそうです。 ステータスの詳細画面はこんな感じで、 Redmineのステータスでは、「終了したチケット」としてステータスを設定すると、 チケットの検索一覧で完了したチケットとして扱われます。 チケット一覧は未完了のチケットのみ表示する設定になっていることが多いので、 もう対応する必要がないチケットを一覧から消し込むことで、先輩上司や運営チームはコメントが捗りそうです。 ステータスの一覧画面はこんな感じです。 この一覧では、このRedmine環境に登場する全てのステータスが表示されています。 日報という業務の流れにおいては、記入済みと完了だけで良いと決めたので、 どこかでこの業務の流れ、 ワークのフロー を指定してやる必要があります。 おまけ:進捗率の2つの考え方 Redmineは、チケット個別に進捗率を手動入力するモードと、ステータスにデフォルトの進捗率を持たせて手動管理しない、二つのモードがあります。 このモードは環境で単一設定のため、どちらかしか選べません。 管理 > 設定 >チケットトラッキングから選べます。 ワークフローの考え方 ワークフローとは、トラッカーとロール別に、カスタムフィールドやステータスの制御を行う設定画面です。 この機能により、新卒は余計な項目の表示を削る、操作できないようにする、完了ステータスに変更できないようにする、などの運用ルールをシステムの機能として設定することが出来ます。 日報トラッカー×新卒のステータス遷移はこんな感じです。 新しいチケットは「記入済み」のみで作成可能で、作成済みから勝手に完了できないようにしています。 一方で、運営ロールは完了しても良いし、誤って完了した場合は記入済みに戻せても良いので、こんな感じになります。 新卒ロールに戻って、フィールドに対する権限タブを見てみましょう。 制約をたくさん入れているのでこんな感じです。 プロジェクトの考え方 チケットは必ずプロジェクトに紐づきます。 プロジェクトでは、使用する機能モジュール、紐づけるユーザーとそのロール、トラッカーとカスタムフィールド、などを定義します。 親子構造にして親が子のチケットをすべてみる、といった事も可能ですが、今回は新卒用の1つのプロジェクトがあれば大丈夫そうです。 モジュールの設定 例えば、ロール側でニュースの機能に権限を振っていたとしても、プロジェクト側でニュースのモジュールをONにしていなければ、このプロジェクトではニュース機能は提供されません。 上図、チケットトラッキングは日報そのものが入ります。wikiはこのシステムの利用マニュアルを記載していて、ファイルはその記事内に添付するためのファイルのために利用しています。 メンバーの設定 メンバー欄は個人情報が満載なので割愛しますが、選んだユーザーがどのロールかを必ず設定します。ここで、誰がどのロールかをプロジェクトに設定していきます。 チケットトラッキングの設定 チケットトラッキングのタブでも、このプロジェクトで使うトラッカーやカスタムフィールドを明示的に指定します。 運用管理者の頭が良ければよいほど、業務フローの派生を単一のトラッカーの設定に落とし込んで提供できるんだと思います。(遠い目) これらを抜かりなく設定すると、利用者の皆様にもおなじみの、 こんな画面がやっと使えるようになります。 チケットの入力画面はこんな感じに仕上がりました。 終わりに 本記事、解説以上マニュアル未満なので雰囲気と謳っていますが、 設定をする時の考え方や雰囲気、伝わりましたでしょうか? 他にも細かい設定やらTipsはたくさんあるのですが、 Redmineの管理者権限がざっくりとやる流れの説明としては以上です。 「へぇ、こんな仕組みになっているんだ」 「あ、こういう事が出来るなら使ってみようかな」 と、思って頂ける方が一人でもいれば嬉しいです。 ・・・てか、めんどくさくね? ・・・まぁ、手間はかかりますよね・・・。 でも、エンタープライズな本格的なものって、大体そういうもんじゃね?という気もします。 Backlogがインスタントラーメンだとすると、Redmineはラーメン屋のラーメンです。 Backlogなら「運用ルールはこうだからね!」だけで終わるもんを、わざわざ運用設計して設定しているので、そりゃ手間暇がかかります。かつ、上手く作れないならカップ麺のほうが美味しいです。運用してれば変更管理もあります。それも手間っちゃ手間。 でも、運用ルールだけで運用できる範囲には限界があります。 限界を超えて声掛けしたりルールを周知したり教育したりミスをダブルチェックするより、 システム制御の方が楽になる、という損益分岐点のようなものが必ずあり、 規模と戦うのであればRedmineのような複雑さが頼もしく、結果的には楽が出来る、という事もあると思っています。 個人的には、カップラーメンより上手いラーメンが作れるなら、そりゃ作ってあげたいという気持ちもあります。根っこはエンジニアだもん。 一方で、やはり運用管理者に一程度の知識経験を求める所から、自由度が高く複雑で難しいのは事実です。 業務フローが頻繁に変わる時期や、個々人で全然違う業務フローの人たちが同じチームです、といった場合、運用者が伴走することのコストは増大します。 また、インフラの運用の側面でもメジャーアップデートへの対応やプラグインの互換性など、それを乗り切るだけのリソースが必要にはなります。 インフラ面においてはホスティングサービスへの移管で軽減されますが、代償としてSQLの直叩きとかメール受信結果をチケットに起票する系の機能は、恐らく使えません。 なにより、UXにおいてはRedmineの管理者権限の機能を理解している人の有無が大きいです。 手作りでも不味いなら仕方ないです。Backlogには勝てません。 お急ぎの新規プロジェクトでRedmineの運用管理経験者がいないのであれば、僕はBacklogを勧めます。 でも、大規模向けなのにオープンソースで無料です。 タダです。 今回は扱っていないですがプラグインによる拡張性もあり、 日本の開発陣の貢献によって2006年からの開発も現在に至るまで連綿と続いていて、 プロダクトとしての安定感も抜群。 AWSのLightsailでもWordPressみたいな感じでサクっと利用可能です。 謝辞 マイナビ社として、Redmineは数多く利用しているOSSの中の1つで、このプロダクトに支えられているプロジェクトが社内には沢山存在します。 改めて、過去から現在までの全ての開発者と開発コミュニティの方に感謝御礼を申し上げます。