チームスピリットデベロッパーブログ

チームスピリット開発者のブログ

Salesforce Developers Meetup #25 でLT登壇しました。

こんにちは、EX開発部の佐藤です。 2021/4/14 に行われた Salesforce Developers Meetup #25 にLTのスピーカーとして登壇しました。

Salesforce Developers Meetup はSalesforce の開発者が集まって様々は技術情報を交換する場です。 今回は#25ということでその25回目ということですね。 trailblazercommunitygroups.com

発表の内容を決めるにあたり、まず自分たちが実際の開発で得た経験を元に発表をしようと考えました。

私たちが開発しているプロダクト、チームスピリットEXは大企業向けのプロダクトであるため、 1 Salesforce 組織に万単位の人数が利用することを想定して開発しています。

それらの経験から得た内容を汲み取って LTでは Salesforce 大規模開発で留意するトピック集 を発表しました。 speakerdeck.com

内容としては、大規模開発で役に立つ小ネタ集になっていて

  • パッケージの分割をしないといけない理由
  • SFDXプロジェクトでクラスがフォルダ分けできる
  • SFのオブジェクトに依存してテストを書くとパッケージングが遅れてしまう
  • オブジェクトのレコード数が20万件を超えるととあるエラーが発生する

など、大規模な開発でやった方が良い内容をまとめています。

登壇では 「知らなかった」「そうだったんだ」という発見の声を数多くいただきました。 そのような声から大規模な開発の経験ってなかなか得られない経験なんだなということを改めて確認しました。

今後も機会があればイベント等には参加していきたいなと思います!

Japan Dreamin' 2021でLT登壇してきました!

こんにちは、倉谷(id:a-kura)です。 少し前になりますが、2021年1月30日(土)に開催された Japan Dreamin' 2021 に参加・LT登壇してきました。

www.trailblazers.jp

LTでは、「なぜ、Salesforceは最強の業務アプリ・プラットフォームなのか?」と題してSalesforce Platformの強みについて話しました。こちらから資料と動画を見ることができますので、よろしければご覧ください。

www.slideshare.net

www.youtube.com

まとめ

今回は、Salesforce Platformの強みである「カスタマイズ性」について、そして業務アプリ・プラットフォームにそのカスタマイズ性が重要な理由について話しました。

Salesforce Platformの優秀さは、ノーコード開発、プロコード開発、アプリ・ストア(AppExchange)などアプリケーションを追加しやすいプラットフォームである以上に、それを使って製品提供されているアプリケーションをカスタマイズできてしまうところです。特に、AppExchangeではアプリケーションを提供・運用するための機能であるISVforceが提供されており、素早く継続的にビジネスを展開できるようになっています。

Salesforce Platformの強みは、Salesforceエスコシステムに関わるすべてのパートナーが活用できるので、これからも使い倒すような発信をしていきたいと思います。

Japan Dreamin' 2021

昨年に続き、今年もJapan Dreamin'を協賛させていただきました。TrailblazerはSalesforce Platformのもう一つの強みなので、これからも応援していきたいと思います。

teamspirit.hatenablog.com

宣伝

弊社、業務拡大に伴い、全方位で一緒に働いてくれる方を募っています。 採用サイトのリニューアル後、社員のインタビュー記事などを定期的に投稿しています。非常に面白い記事になっていますので、ご一読いただければと思います。

recruit.teamspirit.com

そして、大事なことなので、もう一度言います。
一緒に働いてくれる方を絶賛募集中です。

特に、下記の職種にご興味のある方は何卒よろしくお願いいたします。

エンジニアリングチームオールハンズミーティングの感想

TeamSpirit デベロッパーブログでは初登場、グローバルコミュニケーションズのチュア・ヤオウェイと申します。シンガポールの出身です。

イベントの感想

楽しいイベントでシンガポールと日本のコミュニケーションの改善を行いたいという目的で、先月、第1回エンジニアリングチームのオールハンズミーティングを行いました。他のメンバーと一緒にイベントを開催するのは初めての経験でした。上手くいかなかったところもありましたが、全体的にはスムーズに進行したと感じました。今回のイベントを通して、私はいくつかの改善点を学ぶことができました。

今回のイベントで学んだ3つのポイントをご紹介します。 1) 再確認の大切さ 2) 常にバッファを持つこと 3)即興の重要性

再確認の大切さ

企画段階では、必要なものをリストアップし、リストされたものに基づいてイベントを進めました。しかし、人間である私たちは、細部を徹底的に確認せずに、当たり前のことを当たり前のようにやってしまいがちです。頻繁に日常的に使うものや、仕事をするものであればなおさらです。一つ目の例は、グループのメーリングリストで参加者にイベントの招待を送った際に、本番の数日前まで全員がメーリングリストに登録されているかどうかの確認をしていませんでした。別の例では、メンバー全員がConfluenceにアクセスことができるかどうかの確認をしていませんでした。これにより、確認と再確認の重要性を実感しました。特に、日常的に行っていることで、ルーチンワーク化してしまいがちな仕事においては欠かせないものだと思います。

英語では、言葉遊び、ジョークに近い物ですが、「Don’t assume or you will make an ass out of you and me.」というフレーズが有名です。Assumeのスペリングを分解すると、Assume -> ass +u(you)+meとなります。つまり「assume」はass(馬鹿される)をとるとu(あなた)とme (私)になります。ここまでは誰でも理解できると思いますが、ass out of you and me というにはスラングで「君と私が笑い者になる」を言います。「想定や憶測はするな!貴方と私(自分)が笑い者になるだけだ」という意味です。「仮定する」というのはどんなことに対しても良くないと思います。

もっと大きな問題は、多くの仮定は無意識のものであり、私たちが意図的に作っているわけではないということです。私たちの心は、私たちが見たり聞いたり体験したりしたすべてのものについての意見を蓄えて、裏では常に一生懸命に働いているのです。私たちは意識的な努力をして、数秒で修正できるようなミスをしないように注意しなければなりません。これは、お客様に大きな影響を与える可能性があるため、日常業務において特に重要です。

常にバッファを持つこと

物事は常に計画通りに進むとは限りません。そのため、バッファを持つことが重要です。1時間のイベントであれば、予定していた内容は最大で45~50分程度とします。なんとか時間通りにイベントを終えることができたものの、イベントの最初のセグメントの時間をオーバーしてしまったため、ディスカッションや重要な情報の共有のための時間があまり取れませんでした。

人々が何かに熱中しているとき、何かを成し遂げることに集中する傾向がありますが、それは正しいように見えるかもしれませんが、私が今回のイベントで経験したように、実際には生産性レベルの障害となっています。より多くのことを成し遂げるには、最も重要なタスクを完了させることはできませんでした。バッファータイムは、適切に使う努力をしていれば、無駄にはならないと感じています。(例:不測の事態)

即興の重要性

即興でなんとか時間通りに完成させることができました。人間として、即興は大切だと感じています。ルールや時間というのは、私たちにとってはただの指針に過ぎません。決して石に刻まれたものではありません。どれだけ準備をしても、完全にうまくいくことはありません。そのため、即興は重要なことです。(特にTeamSpiritでは、イノベーションやRe:start-upの価値観と結びついているため)

Improvisation(インプロビゼーション)とは発見と創造性のことであり、どの分野でも最高のチームは、発見と創造性(ハードワークとともに)によって等しく活気づけられています。チームの発見は、イノベーションを生み出し、ブランドを強化するのに役立ちます。また、即興を通して、変化は何かを正しくするためのプロセスの一部に過ぎないことを学びます。最後に、私は、即興は確信を持って意思決定をするのに役立つと感じています。人生には「一時停止」というボタンはありません。即興は、私たちに選択を迫り、それを実行し、そして私たちが進むにつれてそれに適応することを強制します。そうすることで、今まで考えたことのない新しいことや方法を発見することができるのです。

最後までお読みいただきありがとうございました。

TeamSpiritのエンジニアキャリアパス構築仕組み紹介

グレード制度及び各グレードのクォリフィケーション

エンジニアのキャリアパス構築仕組みを紹介する前に、まず株式会社チームスピリットの人事制度を説明します。

チームスピリットでは、グレード制度及び各グレードのクォリフィケーションが明確に定義されています。 人事の説明資料を抜粋して、この制度のねらいを概略すると、

➢自身のグレードの職務期待値を理解し、行動規範とする

➢ 会社成長と共に自己成長を実感し、キャリア形成をサポート

となります。

また、上位の「職務クラス」の概念もあり、

✓ 各グレードの上位概念として、職務クラスとして「メンバー」「マネージャー」「ディレクター」の3つに集約される

こととなっています。

キャリアパスについて、下記プロセスを通して、昇格降格を行います。

✓ 上位グレードへの登用については、目標に対する年間を通したパフォーマンスの結果に加えて、 職務クラス・グレード概要で定義した要件を満たしていることを前提とする

✓ 下位グレードへの降格については、目標に対する年間を通したパフォーマンスの結果に加えて、 職務クラス・グレード概要で定義した要件を著しく満たしてないことが継続して判明した場合実施の可能性がある

それから、非常に特徴的なグレード定義として、「マネージャー」及び「ディレクター」の管理監督者に対して、 「ジェネラリスト」と「スペシャリスト(人事労務管理はしない)」の2種類のロール定義があります。

Generalist (Manager)

チームの目標達成や課題解決に対して、自律的にドライブすることができる。 マネージャーとしてチーム全体をリードし、下位層メンバーの目標設定、およびその達成を支援することができる。 その領域に関しての深い専門性を有する。

Specialist

その業務領域においてチームの第一人者として認められ、高度なスキルを元に他チームに対しても影響力を保有すると共に、メンバーにもスキルの継承をすることができる

エンジニアにおけるキャリアオプション

エンジニアという職業は、専門性が高いため、キャリアパスを考える時に、生涯をかけてより高い技術力を追求したいと考えるケースが一般的です。

しかし多くの会社では昇進昇格の道としてプロジェクトマネジャー/課長/チームマネジャーなど管理職のラダーしかありません。 多くのエンジニアによって、より高い給料をもらうために、専門性を犠牲にせざる得ないことは健全ではありません。

チームスピリットでは、「ジェネラリスト」と「スペシャリスト(人事労務管理はしない)」のロールを分けた人事制度によって、有能なエンジニアに複数のオプション提供し、各人がチャレンジしたい道を選択できます。

また、エンジニアグレード概要として、下記のような説明があります。

Manager

マネジメントスキル 50% 専門性 50%

つまり、仕事のリソース配分も、評価のポイントも、専門性とマネジメントの両立が前提となっています。

一方、「スペシャリスト(人事労務管理はしない)」については、専門性100%の指標で業務配分と成果評価を行いますので、専門性を追求しながら上位グレードへのキャリアアップする機会があります。

エンジニアにおけるグレードクォリフィケーション

チームスピリットでは、各エンジニアグレードに対しては、更に明確なクォリフィケーションを定義しています。

エンジニアに、グレードとクォリフィケーションに基づき、現在の自身の立ち位置を明確に把握してもらい、今後のキャリア構築、将来への展望を具体的に描くことが期待されています。

同時にマネジメント層は、グレードの定義に照らして、現状強化するべきクオリフィケーション要件を元に、メンバーと一緒に各人の年度成長計画の策定を支援していきます。

例えば、2020年より、経験の浅いStaffエンジニアグレードに対して、下記のようなクォリフィケーションを設けています。

アジャイル、スクラムでの製品開発手法、Salesforceの基礎知識・プロダクト運用方法を体得し、適切な指導の下スケジュール通りに成果物を仕上げることができる

個々の業務範囲(Scope of work)において、ソフトウェアエンジニアの場合は、

  • タスク工数見積もり
  • ロジカルな情報伝達と設計
  • 詳細設計(例:クラス図、シーケンス図、ER図)
  • コーディング
  • ユニットテストケース設計
  • ユニットテスト
  • バグ修正
  • ドキュメント(機能仕様書やリリースノートまとめなど)
  • 社外技術広報活動

などが要求されます。

もちろん上司やシニアエンジニアからのサポート・アドバイスをもらう前提で業務遂行しますが、各業務の成熟度に基づき、育成計画を策定し、成果に基づき上位グレードへの登用を行います。 育成活動に対して、リソースや費用をかけて実施していくので、予算編成時にきちんと予算の確保が大事になります。

ちなみに、エンジニア組織では、下記の成熟度モデルを定義しています。

  • High 約90%以上の業務が完全に任せられる。
  • Medium サポートとレビューが必要だが、半分前後の業務が完全に任せられる。
  • Low やった事がない、もしくは、基本的に70%以上の業務についてサポートとレビューが必要。

メンバーとマネジャー間は、定期的に、クォリフィケーションと業務遂行範囲の成熟度棚卸しを行い、弱い分野に対してLowをMediumに、MediumをHighに持っていけるようアクションしていきます。

なお、エンジニアに対してスキルマトリクスが作成されていて、組織全体のスキルの可視化も行っています。 今後機会があれば改めて紹介したいと思います。

管理監督者エンジニアのグレードクォリフィケーション紹介

チームスピリットのエンジニア組織では、管理監督者クラスエンジニア、つまり「ジェネラリスト」(マネジャー)及び「スペシャリスト」に対しても明確的なクォリフィケーション定義があるので、紹介させていただきます。

まずマネジャーに対して、

Engineerとして5年以上の経験があり、アジャイル開発・品質管理・プロダクト運用における方法論やポリシー、実践方 法に関して、様々な知識と経験を備えている。

プロダクトデリバリーを確実にするために、Engineerをリードすることがで きる

とのクォリフィケーションがあります。 プレーイングマネジャーであれば、シニアエンジニアの業務を遂行する同時に、より多く経営資源を与えることでより大きな成果と貢献が期待されます。 具体的にはマネジメント業務について下記の業務範囲(Scope of work)が定義がされています。

  • エンジニアチーム文化醸成
  • チームとメンバーの目標設定と実施
  • 公平なOKRと人事評価
  • メンバーのリソース管理・労務管理・メンタルケア
  • メンバー育成計画と実施
  • 開発プロセスの改善と見直し
  • リスクマネジメント
  • 生産性管理
  • 予算・コスト管理
  • 外注管理(ベンダー選定、進捗管理、予算管理、発注管理、稟議、品質管理など)

上記業務についても、エンジニア同様に成熟度モデルを通して、現状業務成熟度を可視化しています。

スペシャリストエンジニアに対しては、

技術に対する幅広い知識と、特定技術領域において高い専 門性を持ち、技術的リーダシップを発揮して、Engineerや PMの問題解決を支援する。

開発方法論・開発標準の確立 や、アーキテクチャ設計、品質管理、ITサービスマネジメント などをリードできる。

先端技術や海外を含めた最新のプラクティスに対する関心 とのクォリフィケーションがあります。

スペシャリストエンジニアの業務範囲(Scope of work)は下記となります。

  • 技術ステコミへ提案し、開発言語、フレームワーク、ライブラリ、プラットフォームなどの技術選定プロセス参加
  • 技術ステコミへ提案し、中長期技術戦略決定プロセス参加
  • PMとプロダクトロードマップ策定(要件実現性や優先順位やリソース計画など)参画
  • 開発ガイドライン策定
  • 技術分科会のリード
  • 全体アーキテクチャー設計と改善
  • 開発プロセスの改善と見直し
  • シニアエンジニアの成果物レビュー

ソフトウェアエンジニア以外に、QAエンジニアに対しても、業務範囲(Scope of work)の定義があります。

例えばスペシャリストQAエンジニアの場合は、

  • 技術ステコミへ提案し、テスト技術選定
  • テスト自動化フレームワーク及び環境開発と構築
  • 会社全般品質改善及び提案
  • 技術分科会のリード
  • 品質保証ガイドライン策定
  • シニアQAエンジニアの成果物レビュー

との内容になります。

まとめ

チームスピリットでは、人事グレード制度をベースにエンジニアのキャリアパスに対して、多様な成長オプションを提供しています。

エンジニア組織では、各グレードに応じて更に詳細な独自のクォリフィケーションも定義されています。 成熟度モデルに基づき、業務遂行範囲の成熟度を可視化し、ビジネスニーズ及び各人の希望により、強みをさらに強くして、弱みを強くしていく仕組みを構築しています。

一度に作った制度は終わりではなく、PDCAの観点で半年おきに定期的に見直しを行っています。 今後見直しの結果も紹介したいと思います。

ユニットテスト初心者がユニットテスト必須の現場で学んだことと、TDDのすすめ

TeamSpirit デベロッパーブログでは初登場、バックエンドエンジニアの尾上です。
以前、アドベントカレンダーでは心理的安全性について個人的な気付きをnoteに書きました。

adventar.org

今回は実際の開発現場で考えたことや気付きを書いておこうと思います。
テーマはユニットテストと少しだけ TDD(テスト駆動開発)です。

突然ですが、
TeamSpirit のバックエンドコードは Salesforce 上で動作するプログラミング言語 Apex で実装しています。

また、TeamSpirit のように Salesforce AppExchange へリリースするためには、
リリース対象の Apex コードについてテストを書く必要があります。

Apex コードの少なくとも 75% が単体テストでカバーされており、かつすべてのテストが成功している。
- Apex 開発者ガイド

ということで

チームスピリットへ入社するまでユニットテスト経験も浅く、
TDD について深い理解も無い自分が、不慣れながらもユニットテスト書いていく上で
やってしまいがちなテストの書き方や改善の気づきについてまとめておきます。

今後ユニットテストを書くことが必須となったがどう書けばよいかわからない、
という方の参考になれば幸いです。


読むのが辛いテストコードを書いていないか

読むのが辛いテストにはいくつかの原因が考えられます。

  • テストメソッド名からテストの内容がわからない
  • ステップが整理されていない
  • テスト用のデータを準備するコードが長く、どこが肝心なテストなのかがわかりづらい

後者の2つについてはこのあとに記載しますが、 テストメソッド名については、長くなってしまっても正確なテスト目的が記載されているほうがよいと思います。

// テストの内容がわからない
static void 休暇申請のテスト3() {}

// テストの内容がわかる
static void 有効期間外の休暇で休暇申請を行うと例外が発生するテスト() {}

上記はサンプルコードです。Apex では日本語のメソッド名が使えないので
自分が実装する場合はメソッドコメントでテストの目的を記載するなどの工夫をします。

これ以外にも読みづらくなる原因はありそうですが、
少なくともコメントでなんのために行っている処理かを補足しておくと、コードを読む際の負担が軽減されます
(これはテストに限りませんが……!)


ステップが整理されていないテストを書いていないか

ユニットテストには4ステップあると言われます

  1. 準備(set up)
  2. 実行(exercise)
  3. 検証(verify)
  4. 後片付け(tear down)

テストコードがそれぞれのステップに分けて書かれていれば
とりあえず大枠の流れを把握した状態でテストコードを読み始めることができます。

// 準備
createTestData();

// 実行
ActualEntity actualEntity = new SampleClass.SampleApi().execute();

// 検証
assertEquals("正常終了", actualEntity.status);

ちなみに Apex ではテストメソッドで作成したデータが永続化されることはなく、
テスト終了後に破棄されるため後片付けの必要がありません。


テストデータを準備するコードがやたらと長くないか

テスト実施あたって、前提となるデータの作成を行うコードが長すぎる/多すぎる
場合があります。

いくつかのテストケースで同じようなデータを作成するのであれば、
ユニットテスト内にテスト用データを作成してくれるメソッドを作成したり、
共通的に必要なテスト用データであれば、テスト用データを作成するテストデータクラスを作成するなどの対応をします。

共通的なテストデータクラスを作成する上で、
どこまで便利に使えるようにするか、については気をつけないと
テストデータクラスがどんどん肥大化してしまうので注意が必要です。

// ==============================
// 複数のテストで同じ準備をしている
// ==============================
@isTest
static void priceが設定されているsampleのステータスを正常終了に更新するテスト() {
    // 準備
    SampleEntity sampleEnt = new SampleEntity();
    sampleEnt.name = "テスト用01";
    sampleEnt.price = 120;
    new SampleRepository().saveEntity(sampleEnt);

    // 実行 & 検証
    assertEquals("正常終了", new SampleClass.SampleApi().execute().status);
}

@isTest
static void priceが設定されていないsampleのステータスを異常終了に更新するテスト() {
    // 準備
    SampleEntity sampleEnt = new SampleEntity();
    sampleEnt.name = "テスト用02";
    sampleEnt.price = null;
    new SampleRepository().saveEntity(sampleEnt);

    // 実行 & 検証
    assertEquals("正常終了", new SampleClass.SampleApi().execute().status);
}

// ==============================
// 共通的な準備は共通化してしまう
// ==============================
@isTest
static void priceが設定されているsampleのステータスを正常終了に更新するテスト() {
    // 準備
    createTestData("テスト用01", 120);

    // 実行 & 検証
    assertEquals("正常終了", new SampleClass.SampleApi().execute().status);
}

@isTest
static void priceが設定されていないsampleのステータスを異常終了に更新するテスト() {
    // 準備
    createTestData("テスト用02", null);

    // 実行 & 検証
    assertEquals("正常終了", new SampleClass.SampleApi().execute().status);
}

不要なテストを書いていないか

前述の通り、Salesforce AppExchange へのリリースはユニットテストによるコードカバー率が 75% を超えている必要があります。

極論、テストの内容がなんであれカバー率が 75% を超えることを目的とすると、
必ず成功するテストをカバレッジ目的で書くこともできてしまいます。

が、本来テストの目的はカバレッジを上げるためではなく、アプリケーションの品質を担保するためのものなので
コードが壊れていても成功してしまうテストでは意味がありません
(自分が業務で関わった範囲でそのようなテストを見かけることはありませんでした!よかった!)

また、意図的でなくても
稀にテスト対象が正しく検証できておらず、失敗することのないテストが生まれていることがあるので
ユニットテストもしっかりメンバーにレビューしてもらう必要があります。

// アサーションが抜けており、常に成功するテストになってしまっている
@isTest
static void XXXXを更新するテスト() {
    // 準備
    createTestData();
    // 実行
    ActualEntity actualEntity = new SampleClass.SampleApi().execute();
}

実行タイミングで結果が変わるテストを書いていないか

テストを書いている時は成功していたけど、翌月に実行してみたら失敗している
といった時限爆弾を仕込んでしまうことがあります。
主に日付や期間などを扱う機能のテストでは気をつけないといけません。

Date.today() といった実行タイミングによって値の変わるものをテストケース内で用いるのも危険ですが、
テスト対象の API の中で today() を利用している場合も注意です。

Date クラスを拡張するクラスを作成し、テスト用の today をセットするといった方法で回避するといった工夫が必要です。

// 実行タイミングによって結果が変わってしまう
@isTest
static void 指定日が操作日より未来であることを判定するテスト() {
    // 準備
    Date targetDate = Date.newInstance(2021, 3, 1);

    // 実行 & 検証
    assertEquals(True, new SampleClass.SampleApi().isFuture(targetDate));
   // → 2021年3月1日以降、このテストは失敗してしまう、、、
}

// Date を拡張した ExDate を利用し、実行タイミングによる結果の変動を防ぐ
@isTest
static void 指定日が操作日より未来であることを判定するテスト() {
    // 準備
    ExDate.customToday = ExDate.newInstance(2021, 2, 28);
    // → today() で返す値をテスト用にセットする
    ExDate targetDate = ExDate.newInstance(2021, 3, 1);

    // 実行 & 検証
    assertEquals(True, new SampleClass.SampleApi().isFuture(targetDate));
}

上記は Apex での書き方です。
また、上記サンプルコードのような today() で返る値をカスタマイズする ExDate.customToday についても実装に注意が必要で
通常機能からの呼び出しを制限しておかないと、操作日=現在日 の前提が崩れてしまいます。

Apex ではテスト実行時のみ private プロパティを参照できるアノテーションや、
テスト実行時のみ True を返すメソッドがあるため、それらを利用してテスト用の操作日をセットすることができます。


テストが書きづらい時は

API の機能が豊富すぎて「シンプルで使いやすい」ことが守られていない可能性があります。

もしこの問題にぶつかった場合は API の設計を見直したり
API 内の責務を分割し、メソッドごとにテストを行うなど、
テスト対象がテストしやすい形になっているか、を疑う場合もあります。

// API の機能が複雑すぎてテストが作りにくい
@isTest
static void XXXがYYYもしくはZZZの場合に、AAAのBBBがCCCであればDDDをEEEに更新するテスト() {
}

また、レイヤードアーキテクチャのような構造になっていて、
(Application層 → Domain層 → Infrastructure層)
Application層のテストはどこまで実施すべきか?
と悩んだ時は、各レイヤーの責務を考えると、テストが書きやすいと思います。

例)
・Application層:入力に対する出力を検証
・Domain層:ドメイン知識による処理を検証
・Infrastructure層:永続化や読み書きを検証


TDD(テスト駆動開発)での改善

まだ自分自身も使いこなせているわけではありませんが、
TDD の考え方に触れることでユニットテストに対する見方が少し変わったので触れておきます。

TDD ってなんだっけ、という方は以下の YouTube リンクをご覧いただくと
丁寧な解説と、サクサクなライブコーディングで楽しく理解が進むと思います!

TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング

TDD は Red → Green → Refactoring のサイクルを回すことで開発する手法です。

  • まずは必要なテストを書き、そのテストが失敗する状態(Red)から
  • テストが成功する状態(Green)を目指して実装を行い
  • テストが成功した状態のまま、実装をきれいにしていく(Refactoring)

ということで、実装よりもまずテストから書いていくため、カバレッジ目的の不要なテストを最初から生むことはありません。

また、上記のライブコーディングでも実演されているように
テストしやすい単位で設計と実装を進めていくため、API に合わせてテストを書くこともなく、テストの抜け漏れも防げそうです。

ただし、TDD はテスト設計のコストをしっかり払う必要がありますし、
機能要件からテスト設計を起こすには慣れも必要で、決して銀の弾丸ではありません。


私自身も普段 TDD を実践できているわけではありませんが
考え方を知っているだけでもユニットテストへの理解が深まったと感じたので
TDD についても触れつつ、ユニットテストについて書いてみました。

これまでユニットテストをしっかり書いたことがないと、意外と気づきにくいことですが
「今後も繰り返し利用されていく」という点を意識するとひどいユニットテストにはなりにくい気がします。
プロダクトコードと同じように新しい機能には新しいテストが追加され、
長い期間、手の加わっていない機能については引き続き利用可能であることをユニットテストが担保しています。

繰り返し利用する、という点ではプロダクトコードとテストコードに差異はなく、
プロダクトコードと同じようにテストコードにも再利用性や保守性の高さが求められます。

今後もより良いテストが書けるようにスキルアップしたいところです。

Salesforceコミュニティイベント Japan Dreamin' 2021 に協賛します!

あけましておめでとうございます!倉谷(id:a-kura)です。

テック系界隈では昨年末も恒例の技術系アドベントカレンダーですごい記事が量産されていて、読むだけでも大変です。
弊社もアドベントカレンダーをやっています。バリバリの技術系というよりは、主にプロダクト開発に関わるチームメンバーの雰囲気、チーム文化が垣間見える記事が多くあり、少し変わった視点で楽しめると思います。

adventar.org

Japan Dreamin' 2021

f:id:a-kura:20201222113347p:plain

さて、本題です。 来る2021年1月30日にSalesforceコミュニティイベント Japan Dreamin' 2021 が開催されます!
弊社チームスピリットも協賛させていただきました!

昨年も協賛させていただきましたが、今年も微力ながらイベントを盛り上げるお手伝いをさせていただければと思います。

www.japandreamin.com

そして、昨年は大きめな会場を提供してもらったにも関わらず、会場に入り切らないほどのTrailblazerが集結しました。今年はどうなるか?

大丈夫です。

今年はオンライン開催となるので、ミーティングサービスのキャパシティが許す限り、参加できます!
現地までは来れない、という方も今年はオンラインなので参加できるようになっています。

セッションについても公開されています。

Astroレーンは今回はPardot関連のセッションが3つあります。 コロナ禍でメールマガジンなどの施策がより活発になったことでノウハウの蓄積が加速しているのかもしれません。

Codeyレーンは開発者のスキルレベルを一段持ち上げてくれそうなセッションが目白押しです。 個人的には「SalesforceインテグレーションパターンとMuleSoftの活用」が気になりました。 f:id:a-kura:20210108105045p:plain

新しい一年も始まりました。良い年になるようにJapan Dreamin'を盛り上げて景気づけしていきましょう!

宣伝

弊社、業務拡大に伴い、全方位で一緒に働いてくれる方を募っています。

採用サイトをリニューアルしました。社員のインタビュー記事などリリース後にも増えていっており、ご一読いただければと思います。

recruit.teamspirit.com

そして、大事なことなので、もう一度言います。
一緒に働いてくれる方を絶賛募集中です。

特に、下記の職種にご興味のある方は何卒よろしくお願いいたします。

社内スクラム研修を開催しました!

先日12/16に、社内の開発チームにてスクラム研修を開催しました。

TeamSpiritでは開発プロセスにスクラムを採用しています。年々スクラムガイドがアップデートされゆく中、私たちも継続的なアップデートと理解深化を目指し、定期的な社内スクラム研修を企画しました。

一般的なスクラム研修は数日間に渡るものも珍しくなく、内容もかなりハイレベルなため、チームメンバー全員が受講するというのはかなりハードルが高く適切ではありません。そこで、外部のスクラムマスター研修を受講し学習したメンバーがこの社内研修で講師となることで、自分たちが利用する開発プロセスを自分たちで学び、活用できるよう「スクラム研修の内製化」を目論んでいます。

研修概要

今回は、外部研修受講者の間でも特に関心の高かった「ストーリー分割」をテーマに開催しました。
zoomを利用して、まず最初に全員で講師の解説を聞き、その後各チーム3~4人に分かれてワークショップを行いました。ワークショップではcacooをホワイトボードのように利用して意見交換をしつつ、テーマへの理解を深めていきした。

f:id:satoishi_ts:20210104193431p:plain

「ストーリー分割」では、まず良いストーリーのための要点「INVEST」、テンプレートとなる「Davis/Cohn」を解説し、また従来型の開発アプローチ(横切り)を例示し、それと異なる分割「縦切り」の解説をしました。
その後、課題を提示し、各チームに分かれてワークショップを行いました。課題は「クライアントが自宅でパーティを企画しています。クライアントから家の掃除を依頼されたものの、家には5つの部屋があり、また家に掃除用具が揃っているのか、家の中が今散らかし放題なのか、すでに片づいているのかどうかも分かりません。」といったものです。各チームでのワークショップでは、「クライアントの家でパーティーを開催するためには、どのようにして家の掃除を進めべきか」をテーマにして議論を深めました。

研修の学び

チーム内では、各メンバーが各々の視点から課題のストーリーの分割を試み、その中で様々な意見が挙がりました。

  • 「客人が泊まるかもしれないので、先に寝室を掃除する」→プロダクトバックログの中でもっとも優先するのはどれか
  • 「どこまで掃除をすればいいか?1部屋に時間をかけると他が終わらない」→つまりまず「完了の定義」を定めなければいけない
  • 「まずはどんな掃除用具があるのかを調べたい」→これはストーリーではなく「タスク」となる

など、それぞれの疑問や考えが、スクラム開発の中でどのポイントに位置付くかの整理に繋がりました。
また、どうしても最初は横切りのタスク化からアプローチしてしまうため、縦切りと横切りの違いについての気付きもありました。

f:id:satoishi_ts:20210104193436p:plain
ワークショップ中のcacooの様子

実務の中では、スクラムの原則に従い綺麗にストーリーにして取り組むのはなかなか難しいものですが、起票時にストーリーとして書いているのか、タスクとして書いているのかに意識が向くだけでも、スクラムの活用レベルを一段階引き上げることができたのではないかと思います。

また3ヵ月リリースである弊社プロダクトの開発サイクルと、2週間リリース前提のスクラム原則の間にあるギャップなども浮かび上がり、メンバー一人一人が自分たちのスクラムをどのようにしてより活用していくか、思考をさらに深めることができました。

今後の取り組み

今回は、スクラムのごくごく一部の要素だけをピックアップして開催しました。
スモールスタートとして1時間だけの開催となったため、まだまだ深堀りしきれていない点も多く、参加者からももっと議論の時間が欲しいなどの感想が挙がりました。

今回は残念ながら時間切れで割愛してしまいましたが、チームでの意見がまとまったところで、各チームメンバーが他チームへ訪問して意見交換をする「ファンアウト」もカリキュラムには組み込んでいました。研修の振り返りでは、次のテーマとして「相対見積もり」や「読書会」なども挙がっており、まだまだ学習していきたい領域、やってみたいカリキュラムは沢山あります。

今後も引き続き社内研修を開催し、社内全体のスクラム習熟度をより高めていきます。