Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

Vim で外部から情報を受ける

この記事は Akatsuki Advent Calendar 2020 の 15 日目の記事です。

thinca です。普段は Vim を使って開発をしています。

Vim は外部ツールとの連携を得意としているソフトウェアで、外部コマンドの実行結果を取り込んだり、Language Server のような外部ツールを起動してデータをやり取りしたり、といったことが行えます。

一方で Vim は、Vim の外部から情報を通知してもらうのが苦手です。

本記事では、まず前半で、Vim が外部から情報を受け取る手段についてまとめます。後半ではこれらを用いて Vim でどのようなことが可能になるかについて検討します。

外部から情報を受ける手法

clientserver

Vim の clientserver 機能は、まさしく外部から情報を受けるための機能です。

clientserver 機能が有効になっている Vim を起動すると、その Vim は外部から情報を受けられるようになります。別の Vim から、別のサーバとして起動している Vim の一覧を取得したり、それぞれの Vim に式を評価させたりすることができます。

この機能には 2 つの問題があります。

  • クライアントも Vim である必要がある
    • これは CLI で vim をワンショットで起動させることで回避が可能です。
  • 環境によっては動作しない
    • 特に Linux 環境においては X サーバとの連携が必要になるため、X の入っていないサーバのようなシステムでは利用できません。

上記の理由から、利用はかなり限定的になります。残念ながら私は、普段はプライベートでは X の入っていないサーバマシンを開発機として使っているため、この機能は利用できません。

Job

Job 機能を使うことで、Vim は外部プロセスを起動してその標準出力を待ち受けることができるようになります。

この機能を使えば外部からの情報の受け取りが現実的に行えます。vim-lsp などはこの機能を使って Language Server から情報を受け取っています。

デメリットとしては、外部コマンドが必要になるため使用するコマンドによっては環境に依存してしまう点です。しかし、最近はシングルバイナリで動作するツールも比較的容易に作れるため、必要であれば専用コマンドを同梱してしまうという手もあります。

ch_listen()

現在はまだ利用できませんが、ch_listen() という関数の追加が提案されています。これがあれば、TCP ポートや UNIX ドメインソケットで入力を受け付けて、処理を実行することができるようになります。Job と違って外部ツールに依存しない点が魅力です。

現在はユースケースが不足していて、必要性についてあと一歩説得力が足りていないようです。もっと実用的なユースケースが提案できれば動きがあるかもしれません。

活用できそうな事例

上記の事情から、私は主に Job を使った方法を利用しています。ここでは、実際にどのような場面で活用できるか、あるいはできそうかを紹介します。

別の Vim でファイルを開く

これは clientserver 機能の主目的とも言えますが、例えばすでに Vim が起動していた際に別の場所で新たに Vim でファイルを開こうとした場合、Vim が複数起動してしまいます。

このとき、新しく Vim を起動する代わりにすでに起動している Vim でファイルを開く、といったことが可能になります。

ファイルの再読み込み

Vim は、開いているファイルが外部で変更されたかどうかは逐一チェックしていません。:checktime Ex コマンドを使うとチェックしてくれますが、必要な際に実行する必要があります。

GUI 版の Vim であれば、例えば Vim のウィンドウがフォーカスを得た際に実行される FocusGained イベントで実行すれば、ほとんどの場合をカバーできそうですが、CUI だと難しそうです。

こんなときに、外部から変更を通知したり、あるいは CUI の Vim がフォーカスを得たことを通知できれば自動でのファイル再読み込みが捗りそうです。

hubot-vimexec

拙作の、チャット上で Vim のコマンドの実行結果を見れるようにする bot です。

thinca/hubot-vimexec

よくある言語処理系の実行結果を出すものと違い、裏で Vim が常駐し、状態を保持しています。なので以下のようなことができます。

f:id:thinca:20201214203600p:plain
状態を保持した bot

これを実現するためには、実行中の Vim に対して外部からスクリプトを与える必要があります。

一番簡単な方法は、Vim 側で新しいスクリプトがないか逐一ポーリングすることです。実際、最初はこの方法で実装したのですが、さすがに 1 秒に何度も readdir() するのはディスクへの負担も気になってきます。

これを Job で置き換えたいのですが、この bot は環境を閉じ込めるために Vim の実行にネットワークを無効にした Docker を使っています。ポーリングの際は、バインドマウントを行ってそこに実行したいファイルを置き、終わったら結果のファイルを置いてもらっていました。これを、Job を使って Vim の内部でプロセスを実行し、外からこのプロセスに対して何らかのアプローチをする必要があります。

そこで、named pipe を使いました。これであればバインドマウントだけでやりとりができます。

まず、マウントした領域にリクエストを受け付けるための named pipe を作成し、Vim はこのファイルを cat コマンドで読み取る Job を生成して待ち受けます。

bot にリクエストが来たら、まずはそのリクエストに対するレスポンスを受け付けるその場限りの named pipe をマウントした領域に生成します。そしてスクリプトの内容と、レスポンスすべきファイル名をリクエスト用のファイルに書き込み、あとはレスポンス用のファイルを、Node.js の fs.readFile() で読み、読み込めるのを待ちます。

Vim 側はリクエストを受けると cat のプロセスがファイルの内容を出力して終了するので、スクリプトを実行し、結果をレスポンス用のファイルに writefile() で書き込みます。その後、次のリクエストのために再び cat の Job を実行します。

bot はレスポンスを受けとると、専用の named pipe を削除し、結果をチャットに伝えます。ちなみにレスポンス用に毎回別のファイルを用意するのは、複数のリクエストが同時に来た場合のためです。

この手法は Windows だと難しいため利用範囲は限られますが、必要なコマンドが catmkfifo だけであるため、Windows 以外であれば比較的容易に応用が効きそうです。

ch_listen() の模倣

ch_listen() はまだ使えませんが、要は、port を LISTEN し、接続があれば入力を標準出力に流し、標準入力から受け取った内容をクライアントに返すようなコマンドがあれば、Job を使って ch_listen() を再現できそうです。

そんな便利なコマンドがあればよいのですが…そんなスイスアーミーナイフのようなコマンドが…アーミー…?あっ!

というわけで netcat を使って ch_listen() のようなことをしてみましょう。

簡易ですが、Vim を起動して、以下のスクリプトを実行します(:source server.vim)。

function s:handle(req) abort
  if a:req.method ==? 'POST'
    return {
    \   'status': 200,
    \   'status_text': 'OK',
    \   'body': execute(a:req.body),
    \ }
  endif
  return {
  \   'status': 404,
  \   'status_text': 'Not Found',
  \   'body': json_encode(a:req),
  \ }
endfunction

function s:parse_request(msg) abort
  let req = {}
  let matched = matchlist(a:msg, '^\v(.{-})\r\n\r\n(.*)')[1 : 2]
  let [header_block, body] = matched[1 : 2]
  let start_line = split(header_block, "\r\n")[0]
  let req.method = split(start_line, '\s\+')[0]
  let req.body = body
  return req
endfunction

function s:out_cb(cxt, ch, msg) abort
  try
    let req = s:parse_request(a:msg)
    let res = s:handle(req)
  catch
    let res = {
    \   'status': 400,
    \   'status_text': 'Bad Request',
    \   'body': v:exception,
    \ }
  endtry

  let response = join([
  \   printf('HTTP/1.1 %d %s', res.status, res.status_text),
  \   'Content-Length: ' .. len(res.body),
  \   '',
  \   res.body,
  \ ], "\r\n")
  call ch_sendraw(a:cxt.in, response)
endfunction

function s:start(port) abort
  let cxt = {}
  let job = job_start(['nc', '-lkp', a:port], {
  \   'in_mode': 'raw',
  \   'out_mode': 'raw',
  \   'out_cb': funcref('s:out_cb', [cxt]),
  \ })
  let cxt.in = job_getchannel(job)
endfunction

call s:start(11111)

サンプルなので処理をかなり省略していますが、どこからどう見ても HTTP サーバです。このサーバは 11111 番ポートで待ち受け、テキストを POST メソッドで投げると Vim script として実行し、結果の出力を返します。

というわけで、curl でアクセスしてみましょう。

$ curl -d 'echo "Hello, Vim server!"' 'localhost:11111'

Hello, Vim server!

結果が返ってきました!やりましたね。

注意点として、netcat には様々な派生バージョンがあるため、実際に使えるかどうかは環境に入っている netcat の機能について知る必要があります。

まとめ

Vim で外部から情報を受け取る手法についてまとめました。また、それらの活用方法についても検討しました。

これらの応用により、Vim をもっと便利にできる可能性があるのではないかと考えています。この記事がその一助になれば幸いです。

ボトルネックマネージャーを抜け出す方法

こんにちは、ゆのん(id:yunon_phys)です。この記事は Akatsuki Advent Calendar 2020 の12日目の記事です。

アカツキは10周年を迎え、それと同時に経営体制が一新され、経営チームExecutive Leadership Team(ELT)が結成されました。 経営戦略の基本方針も変更となり、社内の構造的にも社内の方針としても、アカツキにとって大きな変化のある1年となりました。

私もELTのメンバーとして現在主力であるゲーム事業の職能組織を束ねる立場(Chief of Staff, Games / CoSG)となり、影響の範囲も、責任の範囲も大きく拡大しました。 これまでは、私はVP of Engineering(VPoE)としてエンジニア組織を束ねる立場にあり、一つの職能のことだけを考えておけば良かったです。 しかし今では、エンジニアだけでなく、デザイナーや企画職・QA・マーケターなど、様々な職能を理解し、文字通り全ての人が輝けるように組織を作る必要が出てきました。 昨年の私の個人的なブログで、エンジニア組織だけでなく全体的に良くしたいという記事を書きましたが、1年後にまさかそれが出来る立場になるなんて、未来のことはわからないものですね。

この新しい役割になって、どんな組織を作っていくのか、ご興味のある方は以下のインタビュー記事を読んでみてください。 voice.aktsk.jp

・・・さて、前置きが長くなりました。 CoSGになったという話をしてきましたが、実はVPoEを今も兼任しています。 兼任と言うと聞こえは良いですが、同時に業務をやれるわけではないので、どうしても責任範囲の大きいCoSGの業務が優先されてしまいがちです。 しかし、VPoEとしての業務が無くなるわけではないので、自分がボトルネックになってしまっているのが次第に浮き彫りになってきました。

今回の記事は、そんなボトルネックになってしまったマネージャー業をどうやって抜け出そうとしているのか*1、この1年の取り組みを書いていきます。

Engineering Manager(EM)が同じ情報を持てるようにする

以前はプロジェクトに直接入ったり、1on1する頻度も高く設定していたので、様々なエンジニアに関する情報を自分に集約して様々な意思決定できていました。 しかし、CoSG業が多くなり、エンジニア以外の情報が増える一方で、エンジニアの情報が減っていってしまいました。 特に困ったのが異動・配属で、発生する度に情報をかき集めて、そこに所属しているEMや他のリーダーと交渉して、といったことに追われるようになってしまいました。

この状態を脱却しようと、一度立ち止まって何が問題なのか考えたところ、私に情報を集めようとしている行動そのものが良くないことだと気が付きました。 例えば、異動・配属については、プロジェクトの短期的な課題解決として実行する場合もあれば、中長期的な会社戦略を見据えて実行する場合もあります。 これらを広い視点で実行するためには情報を正しく持っていなければいけない、と思っていました。 しかし、そもそも情報を正しく持っているのが自分だけの状態になっているのが問題でした。

私の信念としては、「同じ情報を持っていれば、全員が同じ意思決定にたどり着く」、です。 裏を返すと、全員が同じ意思決定にたどり着くためには、同じ情報を持っていなければならないということです。

そこで、私に集まってくるエンジニアに関する情報や会社の方針情報などを、可能な限りEMに共有するようにしました。 具体的には、月1回全EMが集まる場を設け、そこで共有しながら、EMの意見を出し合うようにしました。 また、全EMにはそれぞれの抱えているプロジェクトの情報や課題などを共有してもらうようにしました。 全EMが同じ情報を持っている状態を一応は出来たことになります。

これでうまくいくと思ったのですが、残念ながら、私の満足いく結果にはなりませんでした。 それはEMに与えられている権限・責任が適切でなかったからです。 権限・責任が適切でなかったために、EMが自発的にやれる領域を狭めてしまっていました。 そこで、権限・責任を適切に委譲する作業に取り掛かりました。

適切な権限委譲をする

私は適切な権限委譲こそ組織を次の段階に成長させるために、重要な要素だと考えています。 オレンジ組織からグリーン組織のブレイクスルーの一つは権限委譲である、と以下の書籍でも書かれています。

過去には私とCTOとの間でManagement3.0のプラクティスの一つであるDelegation Boardを作りました。*2

hackerslab.aktsk.jp

今回も同じ方法で私と全EMが集まり、Delegation Boardを1日がかりで作成しました。 私はDelegation Boardの結果も大事だと感じてますが、それ以上にそれを決めていく過程こそ意味があると思っています。 実際にこれを作っていく過程でDelegation Levelが一致せず、お互いの想定している権限やそれに伴う責任を丁寧に言語化していきながら、時間をかけて一つ一つ対話していきました。 最終的に出来たDelegation Boardは全員が満足いく結果になりました。

Delegation Boardを作ってから、明らかにEMの動きが変わりました。 何を自分たちがやるべきなのか、どんな責任を持っているかが明確になることが、ここまで強力なのかと改めて理解できました。

EMのサポートを手厚くする

ここまででは、私の負担が下がり、EMへの負担が上がる一方です。 ある意味望んだ結果ではあるのですが、それはあまりに不公平な感じがします。 もし私が逆にEMの立場だったら、今までやったことの無い仕事が増えてしまうので、戸惑ってしまうだろうなと思いました。

そこで、EMの業務をよりサポート出来るように、 @noto さんに各EMの1on1を依頼しました。 @noto さんは私とは違う観点で人と向き合ってくださる方で、とても信頼のおいている方です。 EMの悩みに適切な距離感でアドバイスしたり、聞き役に徹してくださっているようで、早い段階でEMの悩みに解決に向けて動けていってると感じてます。

@noto さんのように第三者的なEMのサポートは、僕のように全てをケアしきれないときに、とても心強い存在です。

何が変わったか

これらの活動により変わったことは、主には以下の通りです。

  • 全エンジニアの状況の見える化シートが自発的に作られ、EM全員でメンテするようになった
  • エンジニアの異動・配置をほぼ私なしで進められるようになった
  • ダイレクト・リクルーティングを私なしで進められるようになった

これまで、自分が記録ではなく記憶にいかに頼りすぎていたのだろう、と感じさせられてしまいました。

これらの業務が自分の手元から離れていくことで、より事業の戦略・戦術の策定に落とし込む時間が増えてきました。 まだまだ自分がボトルネックになっていることはたくさんあるとは思いますが、少しずつでも解消していけるよう工夫していきます。

*1:兼任は続いているので、ボトルネックになっている事実は払拭できていない

*2:Delegation Boardは強力で、これを作る過程とそれによる情報の透明さからすっかり虜になってしまいました。それ以来、社内で何かと権限委譲について語る場面が増えて、Delegation Board作成のファシリテーションを何度もしたことがあります。

新メンバー受け入れ時に各セクションの夕会に参加して回るツアーを実施している話

この記事は Akatsuki Advent Calendar 2020 9日目の記事です。

はじめに

アカツキでサーバサイドエンジニアをしている jyll です。

50人を超える大規模チームのオンボーディングとして、チーム内夕会ツアーを実施してみたら新規メンバーにも既存メンバーにも好評だったので、その際の知見を共有してみます。

チームの構造とリモートワーク下で感じていた課題

私の所属しているプロジェクトは全体で50人以上の大規模チームで、企画職・サーバサイドエンジニア・クライアントエンジニアなどのセクションにおおよそ10人ずつ分かれています。現在はほぼフルリモートワークになっています。

リモート開始前からのメンバーとその後から入ってきたメンバーで情報格差が発生していて、 リモートワーク導入以前から見知っていたメンバーはコミュニケーションに不便をほとんど感じないが、そのあとに入ってきたメンバーは

  • 誰に何を相談したらいいのかわからない
  • チーム全体としてどういった流れで開発が進んでいるのかわからない

などといった不安を抱えてしまうという課題が挙がっていました。

夕会ツアー

そこで、新規メンバーのチーム全体での自己紹介は名前を紹介する程度にしておき、その後各セクションの朝会や夕会に一度ずつ参加して回るツアーを実施してみました。

各セクションの業務になるべく業務に負荷をかけない形で、チーム全体としてはどんな人たちがいて、普段どういう仕事をしているか、誰とコミュニケーションを取っているのかに触れる機会を作ることを目的としています。

各セクションで毎日集まっているミーティングの日程を洗い出して、それぞれ1日ずつ都合のいい日をピックアップしてもらって引率者と新メンバーをそこに混ぜてもらいます。 そこで普段通りの報告を行ってもらったあと、新メンバーとの相互の自己紹介タイムを10分ほど取ってもらう、という流れです。

f:id:jyll:20201209110656p:plain
こんな感じで呼びかけて、その日からさっそく色々なところにお邪魔して回りました。

実際やってみてどうだったか

全体自己紹介後にすぐ担当セクションに引き渡してしまうよりも、丁寧なオンボーディングになりました。 チームとして感じたメリットですと、以下2点が大きかった印象です。

  • 役割の紹介という形ではなく実際に回している業務の話が聞けるので、行なっている業務のイメージがつきやすい
  • 少人数かつ普段一緒に業務をしている人たち中心での自己紹介になるので、より具体的な趣味の話が出てきやすい

おわりに

この試みは実はアカツキの他のプロジェクトで先に導入されていて、そこでうまくやれているとの報告を受けて導入してきたのですが、期待通りの結果が得られました。

大規模なプロジェクトのつながりを作るきっかけとして、簡単に導入できるオンボーディング施策かと思います。おすすめです。

【ハチナイ】完全リモートでクライアントエンジニアインターン【15日間】

こんにちは。イオジンと申します。7月20日〜8月12日まで、15日間インターンをしました。

日本に来て、半年引きこもり生活をしていて、アカツキに内定をもらってインターンを始めました!外国人の中でアカツキにインターンをしてみたいとかアカツキに興味がある人に、有益な文章になってほしいです。

 

目次

  • 自己紹介

  • インターンに参加した経緯

  • 実装

    • システムボイスを鳴らす機能を見直す

    • スキットの話者をProfileID指定にする

    • スペシャルログボのオブジェクトを見直す

    • SDキャラの配置アルゴリズムを見直す

  • 苦労した事

  • 提言

    • Design Pattern

    • C# Convention

    • 本当の日本語

    • チームプロジェクト

  • さいごに

 

 

自己紹介

韓国の東国大学でComputerVisionとか映像処理を勉強しました。

数学とかプログラミングも好きて、学生の時はRayTracing Renderingを作ったりVoxel Renderingを作ったりしました。

f:id:LeeEohJin:20200813114805g:plain

Ray Tracing Rendering

f:id:LeeEohJin:20200813114912p:plain

Voxel Rendering

私は小学校からずっとツクルでゲームを作りました。そしてゲームはストーリーが大事な日本のゲームをモチーフにしているので、将来日本でゲーム開発をしたいと思っていました。

趣味はゲームと昔のJPOPを聞いたり、Netflixでアニメを見たりします。結構、レトロな事が好きなのでゲームとかアニメとか映画も昔のことが好きな変人です。

 

 

インターンに参加した経緯

まずは、私は韓国で大学を卒業して日本に来ました。去年の12月に来て就活を始めました。韓国ではほぼ卒業した後、新卒として就活するのが普通だったので、日本に来てびっくりしました。

そして、コロナが出て私は3月からはずっと自粛生活、でも、就活をずっと続けました。そして、アカツキで内定をもらいました。でも、その時は他の会社でバイトしていたのでそれが終わってアカツキのインターンを始めました。私はハチナイのチームで働くことになりました。

 

 

実装

 

インターンを始めて私がもらった課題は機能を改修する仕事でした。

システムボイスを鳴らす機能を見直す

f:id:LeeEohJin:20200817125240p:plain

鳴らす対象の選手番号が飛び番になった場合に対応できていなかったのが問題でした。

簡単に鳴らす対象を指定できるように、Scriptable Objectを利用して改修しました。

スキットの話者を選手番号指定にする 

f:id:ytfkbc:20201023151233p:plain

スキットではセリフを言う選手は選手の名前に依存していて、選手が同姓同名の場合問題が発生していました。なので、選手の名前の代わりに選手番号を使うようにしました。

そして、変換を誰でも簡単にできるようにするため、UnityのEditor拡張を行いました。

スペシャルログボのオブジェクトを見直す 

f:id:ytfkbc:20201023151859p:plain

(画面は開発中のものであり、実際の仕様とは異なる場合があります)

スペシャルログボのアイテムアイコンが称号、トロフィー、TPを表示出来ない問題がありました。

f:id:ytfkbc:20201023151950p:plain

(画面は開発中のものであり、実際の仕様とは異なる場合があります)

ノーマルログボでは、その問題がなかったので同じオブジェクトにしました。

SDキャラの配置アルゴリズムを見直す

そして、私がハチナイで気になった部分がありました。SDキャラの配置の部分がずっと気になってその部分のロジックを見直したいと言いました。結構細かいところだったが試しに実装をしてみようということになりました。

f:id:ytfkbc:20201023152044p:plain

キャラがランダムに配置されたので、配置がよくない場合がありました。その場合はキャラをクリックするのも不便だし、見た目にも良くないと思って色々アルゴリズムを考えてみました。

f:id:ytfkbc:20201023152111p:plain

(画面は開発中のものであり、実際の仕様とは異なる場合があります)

ガウシアン分布を用いた確率的配置がいいかなと最初は考えましたが、確率に頼るのは完璧な解決方法ではないと思っていました。 そこで毎回配置を確認して最適な位置を探すアルゴリズムを設計して実装しました。

固定の配置場所にしか対応しなかったので採用されませんでしが、問題提起から解決までを自分でやった特別な経験でした。

 

 

苦労した事

外国人として、日本で働き始めた人はみんな同じと思います。時々日本語が聞こえない時があります。リモートではそれはもっと大変になります。

f:id:LeeEohJin:20200813114912p:plain

日本語聞き取れない

Nativeなら、一つの単語とかは聞こえなくても文章を理解する事には何も問題がないですね。でも、私みたいにまだ日本語がNativeレベルじゃない人にとっては地獄です。リモートの環境では時々ネットの問題とかスピーカーやマイクの問題でよく聞こえない場合があります。結構かなりあります。なんかの単語が聞こえなかったらパニックになる時がありました。その時はまた質問するしかなかったです。その時、やっぱり相手には失礼なので、とても申し訳ないと思いました。

現場に初めて飛び込んだ初心者として、苦労した事もあります。学生の時、GitHubを学べる授業もあんまりないし、学生はGitHubを自分のポートフォリオ·サイトとして使えるんじゃないですか?(私はそうでした。笑)

だから簡単な使い方とか簡単な機能しか分からないまま卒業する人が多いと思います。私もそうして、インターンを初めて色々困る時がありました。

  

提言

全般的に見たら、就活で私はかなり珍しいケースと思いますが、今後アカツキにEntryすることになる外国人にとって、私の経験が誰かの手伝いになったらいいなと思う気持ちで伝えたいことがあります。

 

Design Pattern

学校でよく勉強したDesign Patternとかが力になったと思います。MVC Patternで作られたと思って分析すれば、コードレベルではあんまり難しいことは無いと思います。そして、Abstract Factory Pattern(これは明確ではなかった気がします)とかBuilder Patternを使ったコードも見えました。

多分、みなさんが知っていると思いますが、少なくでも、MVC Patternを勉強するためにはStrategy PatternとObserver PatternとComposite Patternの勉強が必要ですね。個人的おすすめ本、二つです。

一番有名なGOF Design Patternsです。

個人的にはこちの方がもっとおすすめです。分かりやすいし、Javaを基にDesignの説明があったのでC#で実装するUnityのエンジニアはコッチがもっと楽と思います。そしてこれを先に見てGOFを見たら改めて見える部分もたくさんありました。 

 

C# Convention

「ハチナイ」 ではC#のStandard ConventionでCodeが出来上がっていますが、前の会社で働く時は、かなり特別なConventionを使って、そのCoventionに慣れて、変な規則のコードをよく書きました。それがちょっと恥ずかしかったので、皆さんはC# Standard Conventionに慣れてください。

 

本当の日本語

本当の日本語?それは何?なら今まで私が学んだ日本語は偽物??と思う人がよくいると思います。本と本当の日本語はちょっと違うと思いました。本ではあんまり説明されてない単語とか文法がたくさんあります。そして、省略不完全な発音です。

その壁を越える方法は色々あると思いますが、私のおすすめは日本の番組です。

番組が一番いいところは単語を省略したり発音をはっきり言わない時がよくあるからです。その環境が一番実戦に近い環境と思います。私もまだまだ足りないですけど、一緒に頑張ってみましょう!

 

チームプロジェクト

一人でゲームを作る事とチームでゲームを作るのは全然違います。一番いいのはチームで作業しながら個人のプロジェクトを続けることがBestです。自分の後を考えて自分が学びたいのを個人プロジェクトにして、チームプロジェクトでは協業ツールの使い方やコミュニケーションの方法と協働してコードを組む方法を勉強すればいいと思います。学校以外で機会は絶対色々あります。

そして、出来ればGitHubをTerminalで作業してみてください。

私もSourceTreeに慣れて、またTerminalに慣れるように勉強しています。SourceTreeでは出来ないし、ちょっと使い辛いのがTerminalで簡単にできる場合が多いと思いました。

大きいプロジェクトを触ると他の人のコードを見る機会とかが良くあるからそれを見るだけで、自分のコード力が上がると思います。本当に難しい課題は、会社が私たちに任せてくれません。難易度よりコードの綺麗さが色々問題になると思います。(私も問題です。。悲)

 

さいごに

私も色々足りないですが皆さんに色々これしてこれして言って恥ずかしいです。これを読む皆さんは私よりもっと実力あるエンジニアと思いますが、でも、なるべく皆さんの成長に私のインターン経験が役に立ったらいいなと思って書きました。

自分の足りないところが見えて、成長の為の良い基盤になったインターンでした。そして優しい皆さんが手伝ってくれるので、不安なくフルリモート環境でインターンをすることができました。ハチナイのインターン楽しかったです❗️ 

読んでくれてありがとうございます。

 

開発エンジニアとQAの心理の違いとは何か?

この記事は Akatsuki Advent Calendar 2020 3日目の記事です。
前回は bluexxsun さんの スプレッドシートの関数では "" を使うな! でした。

はじめに

アカツキでエンジニアをやっている tomotaka-yamasaki です。
この記事では、エンジニアとQAがどのように協力しあってソフトウェアを開発していけば良さそうか、をJSTQBの内容を取り上げつつ書いています。去年のアドベントカレンダーではゲームプログラミングのHP計算システムアンチパターンという記事を書いていました。
hackerslab.aktsk.jp


現在、私はアカツキの子会社であるアカツキ福岡に在籍しており、QA業務の効率化やテスト自動化などを行うチームを立ち上げて、活動しています。私自身、エンジニアとして手は動かしたいので、効率化、自動化を行いながら、QA組織がより良い方向に向かうための手助けも行っています。

この記事を書こうと思った理由

QA組織に直接関わるようになってからテスト関連の知識をメインに取り入れていました。その中で特に印象深かったのは JSTQB*1 です。JSTQBはテスト技術者資格の名称ですが、公開されているシラバスや公認書籍である ソフトウェアテスト教科書 JSTQB Foundation 第4版 シラバス2018対応 に書かれている内容はソフトウェアテストの原理原則です。
www.shoeisha.co.jp


ゲーム開発を経験していた私はその中身を読んで、分かる分かる!と頷きまくっていました。資格試験のシラバスや書籍なので内容はお堅めなのですが、人に紹介するときは、あるある本、と言っています。

f:id:t-yamasaki11:20201203172525p:plain

この記事は 「QAが普段考えていること、思っていること、大切にしていることを開発エンジニアにも知ってもらいたい」 という想いで書きました。
弊社の話ではなく一例ですが、
「QAチームのAさん、いつも細かい不具合ばかりを指摘してきて辛いんだよなぁ…」
や、
「開発エンジニアのBさんに不具合報告すると機嫌悪くなるから言いたくないなぁ…」
など、開発エンジニアとQAメンバーですれ違いが起きているケースは少なからずあると思います。なぜすれ違いは起きるのか、理由は様々なのでこれだ!という解決策を提示することはできませんが、JSTQBを勉強してみて、開発チームが目指した方が良い方向は見えてきた気がしました。

まとめのような話を最初に書きますが、開発エンジニアとQAメンバーはお互いを理解し、尊重することが開発プロセスを円滑に進めるための第一歩だと思います。不具合を出さないためのテスト計画、テスト技法などの具体的な話も重要ですが、それらは良いスタンスの上に積み上がるものだと私は考えています。

前置きが長くなってきたので、そろそろ本題に入ります。「何」を理解すればいいのか、読んでいただける皆様に新しい気付きがあれば幸いです。

この記事のターゲット

  • ソフトウェア開発を行っているエンジニア
  • 開発エンジニアとQAメンバーがなぜかよくぶつかるなぁと思っている方
  • エンジニアは何考えているかよく分からないなと思っているQA関係の方

QAチームを「テストの7原則」から理解してみる

ソフトウェア業界では様々な原理原則が存在しますが、JSTQBの元となっている ISTQB*2 では テストの7原則 として定義されています。普段開発に関わっているエンジニアやQAメンバーは、感覚や経験により理解しているかもしれません。とはいえ、言語化されていることは大変ありがたいことです。この7原則で語られている内容はテスト計画の基盤であり、QAメンバーがテストをする上で大切にしていることです。テストを語る際の共通言語にもなり得ると思っています。

テストの7原則

  1. テストは欠陥があることは示せるが、欠陥がないことは示せない
  2. 全数テストは不可能
  3. 早期テストで時間とコストを節約
  4. 欠陥の偏在
  5. 殺虫剤のパラドックスにご用心
  6. テストは状況次第
  7. 「バグゼロ」の落とし穴

私の意見も交えながら順番に説明していきます。

1. テストは欠陥があることは示せるが、欠陥がないことは示せない

テストにより、欠陥があることは示せるが、欠陥がないことは証明できない。テストにより、ソフトウェアに残る未検出欠陥の数を減らせるが、欠陥が見つからないとしても、正しさの証明とはならない。*3

欠陥とはバグのことだと思ってください。欠陥が無いことの証明は、いわゆる悪魔の証明です。一定のテスト期間を経て欠陥が全て修正され、1週間欠陥が見つからなかったとしてもプロダクトの品質が高いことの証明にはなりません。なぜならテスト自体に不備があり、欠陥を発見できていないパターンを排除できないためです。
なので、QAチームはテストに不備がないかどうかを、発見した欠陥数を見て判断したりします。欠陥は必ず出るものだと認識し、テスト実行数と欠陥発見数を比較します。これまでの実績があることが前提になりますが、テスト実行数のわりに欠陥数が不足している場合はテストの不備を疑います。

また、この原則が存在するため、「テストの終了基準は欠陥がなくなること」にすることはできません。どうすればテスト終了なのかを定義することはQAチームの役割です。ISO/IEC 25010で規格されている品質特性を満たす、という定義も考えられます。いずれにしても、定義への合意は開発チーム全体で行うことだと思います。

2. 全数テストは不可能

すべてをテストすること(入力と事前条件の全組み合わせ)は、ごく単純なソフトウェア以外では非現実的である。全数テストの代わりに、リスク分析、テスト技法、および優先度によりテストにかける労力を集中すべきである。*4

おそらく原則2を満たすことができれば原則1の証明になるんですが、現実はそこまで優しくできてはいません。電卓のようなアプリケーションですら全ての入力と計算を網羅することはできません。ゲームアプリケーションはもっともっと複雑です。スキルの組み合わせ爆発が起きている、なんて話を色んな所で耳にします。
同値分割というテスト技法のように組み合わせを減らす考えも重要ですが、ここで私が一番重要だと思うことは、テストには実行優先度があるということです。優先度をつけると以下のようなケースで役に立ちます。

  • リリースタイミングが迫っていて、工数が足りない場合
  • リグレッションテストの工数がテストスケジュールを圧迫している場合

どのテストから行うべきかを予め決めておくことで、いざというときに即時対応できます。更に、テストケースを削減するタイミングで、どの程度品質が落ちるのかを明言できると素敵です。リスク分析は実行優先度を決めるための手段の一つであるとも言えます。

また、作り手である開発エンジニアの方が優先度を付けやすいケースもあると思います。ユニットテストである程度品質が担保されている箇所や、同じ関数を使用している箇所があれば優先度を下げることもできるはずです。開発エンジニアが協力して、テストにかける労力を減らせると良いなと思います。

3. 早期テストで時間とコストを節約

早い段階で欠陥を見つけるために、静的テスト活動と動的テスト活動の両方をソフトウェア開発ライフサイクルのなるべく早い時期に開始すべきである。早期テストは、シフトレフトとも呼ばれる。ソフトウェア開発ライフサイクルの早い時期にテストを行うことにより、コストを低減または削減できる。*5

QAを「最後の砦」と呼ぶこともありますが、私はそう呼ばれないようになるのが本来のQAの在り方だと考えます。砦ではあるけど、最後ではなく、出来ているところから見ていくような、開発と同時並行で検証できるのが理想です。

テストはテスト対象が完成してから始まるものではありません。開発エンジニアが設計を行う前、ディレクターが仕様書を作り始めるところからテストは始まっています。QAメンバーが仕様書をレビューし、仕様の抜け漏れをチェックする、ゲームであれば面白いものなのかをチェックする、などの行為もテストに該当します。
最後の最後に検証すると、欠陥が見つかったときのコストが早期発見したときと比べ、2,3倍にも膨れ上がります。テスト工数にいくらバッファを積んでもスケジュールを圧迫してしまうのは、このような影響要素が多すぎるからです。従って、シフトレフトによってできる限り早期にテストし、テストプロセスに影響する不確定要素を排除することができます。

アカツキのQAメンバーは、仕様書ができた段階でテスト観点を洗い出し、その仕様を実装するメンバーで観点をレビューしています。そうすることで膨大なテストケースを作る前にテストの抜け漏れを発見することができ、欠陥の早期発見に繋がっています。

一方で、開発エンジニアはCIによってPull Requestごとに自動テストを回せるようにしています。ソースコードが本流にマージされる前に欠陥を見つけることは大変効果的です。
このように、開発エンジニアとQAの双方がシフトレフトの概念を理解し、実施していくことが大切だと思います。

4. 欠陥の偏在

リリース前のテストで見つかる欠陥や運用時の故障の大部分は、特定の少数モジュールに集中する。テストの労力を集中させるために欠陥の偏在を予測し、テストや運用での実際の観察結果に基づいてリスク分析を行う。(原則2で触れたことと同様)。*6

ゲームアプリケーションだと、インゲームのような複雑な処理を行うコードは欠陥が混入しやすい箇所だと思います。開発エンジニアはソースコードを読むことができるため、「複雑な処理を行うことでコードが複雑になっていたり、場当たり的な対応を行っている箇所だったり、に欠陥の偏在があるだろう」、と推測することができますが、QAメンバーは過去の欠陥の傾向などから偏在を推測するケースが多いと思います。欠陥の偏在箇所を特定することは、テストの優先度を決定することに繋がります。そこを優先的にテストすることで早期に欠陥を見つけることができます。

欠陥の偏在を見つけるためにはエンジニア的な視点が必要だと考えています。エンジニア的視点とは、システムの概要を理解する、データ構造を理解する、ソースコードを読み複雑度を理解する、などです。発生する欠陥を推測するテスト技法はエラー推測とも呼ばれますが、偏在箇所を合理的に推測することができれば効果的にテストを行うことができます。QAチーム側でエンジニア的視点があるメンバーがいれば良いですが、それは稀有なので開発エンジニアがQAチームにエラー推測の観点を伝えることが重要だと考えます。

また、Aさんは開発スピードは早いが欠陥は多い、などの開発エンジニアの特性を伝えることも一定効果はあると思います。ただし、そこでAさんを批判するべきではありません。欠陥が多い、という事実にフォーカスして非難にならないように伝えることが大切です。

5. 殺虫剤のパラドックスにご用心

同じテストを何度も繰り返すと、最終的にはそのテストでは新しい欠陥を見つけられなくなる。この「殺虫剤のパラドックス」を回避するため、テストとテストデータを定期的に見直して、改定したり新規にテストを作成したりする必要がある(殺虫剤を繰り返し使用すると効果が低減するのと同様に、テストにおいても欠陥を見つける能力は低減する)。ただし、自動化されたリグレッションテストの場合は、同じテストを繰り返すことでリグレッションが低減しているという有益な結果を示すことができる。*7

同じシステムに対して、同じテストを繰り返していても新しい欠陥を見つけることができないことは理解できます。ただ、ゲームアプリケーションは高い頻度でアップデートを行っているため、同じシステムで動き続ける期間は短めです。コードの変更によるデグレード(リグレッション)を防ぐために行うテストがリグレッションテストですが、この場合に限り、殺虫剤のパラドックスは有益なものとなります。リグレッションテストは繰り返すことで初めて効果を発揮します。これまでと同じ挙動をしているかどうか、認識しているコード修正の影響範囲以外の箇所で欠陥が残っていないかなどを網羅的にテストすることが可能です。

しかしながら、リグレッションテストは広範囲を網羅的にテストしがちなので、手動で、繰り返し行うと工数が膨れ上がります。そのため、アプリケーションのアップデートごとに1周だけテストするのみ、という場合も多いと思います。

リグレッションテストは繰り返し行うことで効果を発揮するため、最も自動化に向いていると言われています。このテストをうまく自動化し、CIに組み込むことができれば原則3の早期テストに大きく貢献することができ、QAの工数を削減することができるはずです。自動化はQAだけでは実現困難なので開発エンジニアの手が必要になります。SETと呼ばれるテスト自動化を専門とするエンジニアに依頼するのも一つの手段だと思います。

6. テストは状況次第

状況が異なれば、テストの方法も変わる。例えば、安全性が重要な産業用制御ソフトウェアのテストは、eコマースモバイルアプリケーションのテストとは異なる。また、アジャイルプロジェクトとシーケンシャルライフサイクルプロジェクトでは、テストの実行方法が異なる。*8

ここで得られる重要な示唆は、全てのテストには目的が存在する、ということです。状況が異なれば、テストの目的も変わり、それによってテストの方法も変わります。JSTQBにはテストプロセスの原理原則は書かれていますが、それは単なる武器に過ぎません。何を、どのように使用するかを計画することがQAの役割です。開発エンジニアがテストに関心を持ち、QAメンバーとテストの目的について議論することはとても有意義だと思います。自ら書いているユニットテストの目的について考えてみてもいいかもしれません。

7. 「バグゼロ」の落とし穴

テスト担当者は可能なテストすべてを実行でき、可能性のある欠陥すべてを検出できると期待する組織があるが、原則2と原則1により、これは不可能である。また、大量の欠陥を検出して修正するだけでシステムを正しく構築できると期待することも誤った思い込みである。例えば、指定された要件すべてを徹底的にテストし、検出した欠陥すべてを修正しても、使いにくいシステム、ユーザーのニーズや期待を満たさないシステム、またはその他の競合システムに比べて劣るシステムが構築されることがある。*9

欠陥を全て見つけること、そして全てを修正することを目的に置いてはいけません。欠陥を修正した結果、システムにどういう影響が発生するのかを認識しないといけません。欠陥は修正できるが、操作性が失われる、ソースコードのメンテナンス性が失われるなどデメリットが大きければ第三の案を考える必要性も出てきます。

しかしながら、QAメンバー全員が欠陥の修正方針を考えられるわけではありません。システムの内部構造まで理解していないと修正方針は立てられないからです。修正することでどのような影響があるのかを考えることは開発エンジニアの役割です。欠陥に対して、開発エンジニアとQAメンバーは真剣に向き合わなければなりません。そのために、最高品質のプロダクトをリリースする、といった共通の目的を設定すると良いと思います。

開発エンジニアとテスターの心理の違い

開発エンジニアの確証バイアス

人には 「確証バイアス」 と呼ばれる心理的要素が存在します。

確証バイアスと呼ばれる人の心理の要素は、持っている信念に合わない情報を受け入れがたくする。例えば、開発担当者は、コードは正しいという思い込みがあるので、確証バイアスにより、コードが正しくないということを受け入れがたい。*10

開発エンジニアは確証バイアスによって自分のコードに自信を持っているケースがあります。ここでいう自信は、「私の書くコードにバグなんてありえない!」というものではありません。自分で作ったから内部構造も分かる、Pull Requestを出しコードレビューも行った、更に自分で入念に動作チェックもしたから問題ない、その過程で出たバグは潰したからもう他には存在しないだろう、という論理ありきの自信です。しかし、その努力、行動の結果、確証バイアスが生まれると思っています。

自分を客観視しないと確証バイアスは無くなりません。自分以外のエンジニアがコードレビューすることによって下がりますが、それでもエンジニアとしての確証バイアスがあるため、0にはならないと思います。確証バイアスがあると、欠陥報告が自分への非難と捉えてしまう場合があります。


確証バイアスがあることを前提に、QAメンバーはJSTQBで定義されている以下のスタンス*11 でテストに臨みます。

  • 対決ではなく、協調姿勢で開始する
    • 全員のゴールは、高品質のシステムであることを再認識するとよい。
  • テストの利点を強調する
    • 例えば、開発担当者に対しては、欠陥情報は、作業成果物の品質向上と開発担当者のスキル向上に役立つ。組織に対しては、欠陥をテストで検出して修正すると、時間と経費の節約になり、プロダクト品質の全体的なリスクも減る。
  • テスト結果や他の発見事項は、中立な立場で、事実に焦点をあてて伝え、欠陥を作りこんだ担当者を非難しないようにする
    • 客観的かつ事実に基づいた欠陥レポートを書いたり、発見事項をレビューしたりする。
  • 他人の気持ちや、他人が情報に対して否定的に反応した理由を理解するように努力する
  • 自分の言ったことを他人が理解し、他人の言ったことを自分が理解していることを確認する

開発エンジニアとQAのマインドセットの違いを理解する

f:id:t-yamasaki11:20201203172529p:plain

開発エンジニアとQAの仲が悪い、という話を聞いたことはありませんか?

開発担当者とテスト担当者は、異なった考え方をすることが多い。開発担当者の主目的は、プロダクトを設計して構築することである。テストの目的は、これまでに説明しているように、プロダクトの検証と妥当性確認、リリース前の欠陥の検出などである。このように目的が異なっており、異なるマインドセットを必要とする。両者のマインドセットを組み合わせることで、より高いレベルのプロダクト品質を達成できる。*12

仲が悪くなってしまう原因として、開発エンジニアとQAでマインドセットが異なるから、ということが考えられます。お互いに興味関心ごとが違うため、意志決定と問題解決において前提とするものと優先する方法が異なり、それが両者の壁になります。

開発エンジニアのマインド

解決策の設計と構築に大きな関心があります。また、確証バイアスが自分自身の作業中に犯した誤りを見つけることを困難にしています。

QAのマインド

好奇心、プロとしての悲観的な考え、批判的な視点、細部まで見逃さない注意力、良好で建設的なコミュニケーションと関係を保つことに関心があります。また、テスト担当者のマインドセットは経験を積むに従って成長し成熟する傾向があります。


重要なことは、まず、開発エンジニアとQAがお互いに持っているマインドの専門性を理解し、不足している部分を補完し合うことだと思います。そしてプロダクト品質を向上させる、といった共通の目的を軸に議論することが大切だと考えています。この内容は、TeamGeekで紹介されている HRT(謙虚、尊敬、信頼)*13 と似たものを感じました。

まとめ

冒頭でもお話しましたが、この記事は、QAが普段考えていること、思っていること、大切にしていることを開発エンジニアにも知ってもらいたい、という想いで書きました。QAが大切にしていることは、テストの基盤となる考え方であるテストの7原則や、相手を非難せず協調姿勢でいる、といったヒトではなくコトに向かうスタンスです。そして、開発エンジニアとQAのマインドの違いについても紹介しました。互いに理解し、共通の目的を持つことでエンジニアとQAのシナジーが生まれ、健全な開発が行えると信じています。

補足: 所属チームの取り組みについて

現在は、A4というチームに所属し、今回書いた内容などを基にQA組織の在り方を再構築しています。他にも業務効率化やテスト自動化なども行っていますが、アカツキ福岡でA4チームが大切にしていることは以下にまとめています。
fukuoka.aktsk.jp

A4チームの取り組みについて、記事を書いてもらいました。せっかくなので紹介させてください。
www.wantedly.com

長々と書いてしまいましたが、ここまで読んでいただいた方、本当にありがとうございます。
この記事が新しい気づきになりましたら幸いです。

===

*1:JSTQBとは、日本におけるソフトウェアテスト技術者資格認定の運営組織で、 各国のテスト技術者認定組織が参加しているISTQB(International Software Testing Qualifications Board)の加盟組織として2005年4月に認定されています。 JSTQB認定テスト技術者資格-JSTQBについて-

*2:ISTQB® has created the world's most successful scheme for certifying software testers. As of October 2019, ISTQB® has administered over 920,000 exams and issued more than 673,000 certifications in over 120 countries world-wide. The scheme relies on a Body of Knowledge (Syllabi and Glossary) and exam rules that are applied consistently all over the world, with exams and supporting material being available in many languages. Certifying Software Testers Worldwide - ISTQB® International Software Testing Qualifications Board

*3:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.17

*4:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.17

*5:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.17

*6:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). pp.17-18

*7:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.18

*8:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.18

*9:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.18

*10:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.25

*11:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.26

*12:ISTQB. “ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2018V3.1.J02”. JSTQB 認定テスト技術者資格. 2019-11-11. http://jstqb.jp/dl/JSTQB-SyllabusFoundation_Version2018.J02.pdf , (アクセス日 2020-12-03). p.26

*13:Brian W. Fitzpatrick, Ben Collins-Sussman, 角 征典 (2013). Team Geek ―Googleのギークたちはいかにしてチームを作るのか オライリージャパン pp.15-18.