mongolyyのブログ

開発(Javascript, Typescript, React, Next.js)や開発手法(スクラム, アジャイル)、勉強したことについて色々書ければと。

Developing Solutions for Microsoft Azure(AZ-204)の合格体験記

はじめに

今回、Developing Solutions for Microsoft Azure(AZ-204)に合格したので、その体験記を共有します。

私の情報

AWS認定DevOps Engineer ProfessionalとAZ-900は取得済み。
業務ではAzureのとあるサービスを半年ほど利用しているので、全体感は何となくわかっている。

どのくらい勉強したか?

勉強時間は6~8時間くらい。
期間は1週間くらい。

何を使用して勉強したか?

次の問題集を全部やりました。

www.udemy.com

時間がないときは、Udemy用の一問一答の拡張機能を使用して、細切れに問題を解きました。

chrome.google.com

試験を受けてみて

実際にAzureを触っているかどうかが問われるような問題が多かったです。
問題集で範囲を確認したうえで、自分が触ったことないサービスは一通り触ってみることをお勧めします。
サービスを触ってみて、サービスを起動するためのオプションや設定の違いを理解しておくとよいと思います。
また、AWSGCPとも似たサービスが多いので、そちらのAssociateレベルの資格を持っている場合はその知識が活かせると感じました。

【スクラムの実験カタログ】毎日レビュー

はじめに

メーカーのコーポレート部門でソフトウェアエンジニアとスクラムマスターをやっているモンゴルです。 スクラムでの実験の中で良さそうなものを紹介していきたいと思います。

第4回目は毎日レビューです。

毎日レビューとは?

通常1スプリントで最後に行う、スプリントレビューを毎日やることです。
朝会や夕会前後で15~30分程度時間を取ってやります。
内容はスプリントレビューと同様で、完成したものを共有して、「もっとよくするには?」という観点でチームで議論します。

どういうチームにおすすめの実験か?

  • 通常のスプリントレビューで、これって問題あるよね。というのがよく見つかるチーム
  • 通常のスプリントレビューで成果物がたくさんあるチーム
  • フロー効率を上げたいチーム
  • PBIが大きすぎるチーム

この実験で気づけること

  • スプリントレビューでのフィードバックの大切さ
    • 通常のスプリントレビューと比べて時間に余裕があるので、フィードバックが豊富にでき、良い気付きが得やすくなる
  • ペア作業、モブ作業でフロー効率が上がる
    • 毎日スプリントレビューがあるので、「明日やればいかー」ではなく、「今日中にここまでやろう」という気持ちになる
    • それにより、ペアプロ、モブプロでさくっと解決して今日のレビューに出そうというフォースが勝手に生まれたりもする
  • タスクの細分化の重要性
    • 毎日のスプリントレビューでコンスタントに成果物を出すために、タスク細分化のフォースが発生する
    • 結果として、「細分化するとリスクが減らせる」といった、細分化の重要性を体感することができる
  • 毎日、自分がやったことをみんなに見てもらえると嬉しいということ

終わりに

某チームでこの実験をしたところ、着手中やレビュー中にあるPBIが激減しました。

やってみて、「こんな発見があったとか、こういうふうにやるといいよ!」とかあれば、是非コメントを!

【スクラムの実験カタログ】WIP制限を加えてみる

はじめに

メーカーのコーポレート部門でソフトウェアエンジニアとスクラムマスターをやっているモンゴルです。 スクラムでの実験の中で良さそうなものを紹介していきたいと思います。

第3回目はWIP数に制限を加えるです。

WIP制限とは?

カンバンのプラクティスが由来です。

www.atlassian.com

WIP数の制限はチームの規模によって決めるといいと思いますが、メンバー数の半分~同一くらいから始めるのがおすすめです。
チームでこの実験に対してどのような期待を寄せているかに合わせて調整するといいと思います。

どういうチーム、ケースにおすすめの実験か?

  • ペアプロ、モブプロをもっとやってみたいなーというチーム
  • フロー効率をもっと上げたい/課題があるチーム
    • 例えば、レビュー中にPBIが滞留しているなど

この実験で気づけることの例

  • フロー効率を上げるためのコミュニケーションのあり方
      • レビュー依頼するときにこういう声がけすると良さそう
      • レビュー後にペア、モブで議論しながら進めると早いね
      • 課題を取る前に声掛けすることで、タスクのサポートがしやすくなり、負荷が集中することが減るよね
  • モブ、ペアでやれば新しいこともやれること
      • 今までインフラ系は〇〇さんがやってたけど、〇〇さんがサポートしてくれたら私達もちょっとできるね。〇〇さんに負荷が集中していたし、みんなで少しずつやっていこう。
  • レビューが迅速だと、スプリントレビュー前日、直前に仕事が溜まらないこと

おわりに

この実験により、開発プロセス、コミュニケーションのあり方について模索するきっかけとなると思います。

やってみて、「こんな発見があったとか、こういうふうにやるといいよ!」とかあれば、是非コメントを!

【TypeScript】2つの型システムが混在することを意識すべしという話

TypeScriptを使っているなかで、気になった挙動に遭遇したので備忘録として残しておきます。

例えば、標準のErrorクラスを拡張して、InvalidError というカスタムエラーのクラスを作るとします。

class InvalidError extends Error {
    constructor(message: string) {
        super(message)
        this.name = 'InvalidError'
    }
}

先程定義した InvalidError 型の変数を引数に取る、関数を作ります。

const someFunc = (err: InvalidError) => {
    if (err instanceof InvalidError) {
        console.log('invalid errorだよ')
    } else {
        console.log('invalid errorじゃないよ')
    }
}

呼び出してみます。

someFunc(new InvalidError('hoge'))
// [LOG]: "invalid errorだよ" 

もちろん想定通り動きました。

引数に、標準のErrorインスタンスを与えてみます。

someFunc(new Error('piyo'))
// [LOG]: "invalid errorじゃないよ"

標準のErrorインスタンスは、引数で指定されている InvalidError の親クラスなので、一見すると引数の型が不一致であるように見えますが、IDE上でも実行時もエラーの表示がありません。

一方 instanceof の判定は false となっていました。

「挙動がおかしい?!」と、一瞬思いましたが、タイトルにあるとおり、2つの型システムの違いからこのような挙動の差が生まれています。
引数での型指定と、instanceofでの型チェックはチェックされるタイミング、チェックされ方が異なるのです。

引数での型指定

トランスパイル時にチェックされます。したがって、TypeScriptの型システムの考え方に従って、チェックされます。
トランスパイルされたコードを確認してみると、次のようになっています。

const someFunc = (err) => {
    if (err instanceof InvalidError) {
        console.log('invalid errorだよ');
    }
    else {
        console.log('invalid errorじゃないよ');
    }
};

型指定はなくなってますね。
このことからもTypeScriptの型システムのみでチェックされていることがわかります。
(トランスパイルされたJavascriptのコードに型情報がなければ、Javascriptでチェックしようがないですよね)

TypeScriptの型の考え方ですが、「構造的部分型」という考え方で構築されています。

詳細を知りたい方は、例えば次のページを参照されると良いと思います。

typescript-jp.gitbook.io typescriptbook.jp

今回作成したカスタムクラスと、標準のErrorクラスは構造が同じになっています。
したがって、TypeScript的には型は同じということでエラーや警告は出ません。

エラーや警告を出すためには、次のように、標準のErrorクラスにはないフィールドを定義するようにするといいと思います。
(idのリテラル型の指定や値の指定が煩雑なので、もっといいやり方を知っている方いれば、ぜひ教えてください)

class InvalidError2 extends Error {
    id: 'InvalidError2' = 'InvalidError2'
    constructor(message: string) {
        super(message)
        this.name = 'InvalidError'
    }
}

const someFunc2 = (err: InvalidError2) => {
    if (err instanceof InvalidError2) {
        console.log('invalid errorだよ')
    } else {
        console.log('invalid errorじゃないよ')
    }
}

someFunc2(new Error('piyo'))
// IDEなどで次のようなエラーが表示される
// Argument of type 'Error' is not assignable to parameter of type 'InvalidError2'.
// Property 'id' is missing in type 'Error' but required in type 'InvalidError2'.

instanceofでの型チェック

トランスパイルされたあとのJavascriptのコードを確認してみます。

const someFunc = (err) => {
    if (err instanceof InvalidError) {
        console.log('invalid errorだよ');
    }
    else {
        console.log('invalid errorじゃないよ');
    }
};

instanceofはJavascriptの関数なので、Javascriptのコードにそのまま残っています!!
つまり、Javascriptのルールに従って型のチェックがされます!

Javascriptはプロトタイプベースの型システムが構築されており、prototypeを辿っていって、継承関係があるかどうかチェックしていきます。 詳しくは、次のMDNのドキュメントを読まれるといいと思います。

developer.mozilla.org

今回、InvalidError はprototypeが InvalidError になっているので、instanceofはtrueとなります。
しかし、標準のErrorのprototypeチェーンには Objectnull しかいないので、instanceofはfalseとなります。

おわりに

TypeScriptで型のチェックと言っても次の2つのチェックタイミング、型システムが混在することを意識しなければなりません。

  • トランスパイル時
    • TypeScript:構造的部分型によるチェック
  • 実行時
    • JavaScript:名前的部分型?(prototypeベースの継承)による型の判定

今回作ったコードはTypeScript Playgroundでも公開しているので、みなさんも触って確認してみてください

TypeScript: TS Playground - An online editor for exploring TypeScript and JavaScript

TypeScriptで共通なstaticプロパティを定義する

最初にやろうとしたこと

interfaceでstaticプロパティを宣言して、その実装クラスで初期化しようとしました。

interface MoneyIF {
  static readonly CurrencyUnit: string
  readonly amount: number
}

class JPY implements MoneyIF {
  static readonly CurrencyUnit: string = 'Yen'
  readonly amount: number

  constructor(amount: number) {
    this.amount = amount
  }
}

class USD implements MoneyIF {
  static readonly CurrencyUnit: string = 'Dollar'
  readonly amount: number

  constructor(amount: number) {
    this.amount = amount
  }
}

が、残念ながらinterfaceで次の表示が、、

// static' modifier cannot appear on a type member.

oh...

abstract classで表現してみる

github.com

を中心に議論されていますが、現在のバージョンでは、interfaceでstaticプロパティ、メソッドは定義できません。
まだ結論は出ていないようですが、abstract classで宣言する人たちが一定数いることがわかり、手軽に実装できそうでもあったのでその方針で実装してみました。

abstract class MoneyBase {
  static readonly CurrencyUnit: string
  readonly amount: number

  protected constructor(amount: number) {
      this.amount = amount
  }
}

class JPY extends MoneyBase {
  static readonly CurrencyUnit: string = 'Yen'

  constructor(amount: number) {
    super(amount)
  }
}

class USD extends MoneyBase {
  static readonly CurrencyUnit: string = 'Dollar'
 
  constructor(amount: number) {
    super(amount)
  }
}

const usd: MoneyBase = new USD(100)
console.log(usd.amount)
// 100
console.log(USD.CurrencyUnit)
// "Dollar"

いい感じに扱えそうです。
ただここで新たな問題が、、

console.log(usd.CurrencyUnit)
// Property 'CurrencyUnit' does not exist on type 'MoneyBase'. Did you mean to access the static member 'MoneyBase.CurrencyUnit' instead?

インスタンス経由ではstaticプロパティにアクセスできないのです。。

インスタンス経由でstaticプロパティにアクセスする

ちょっと調べてみたところ、いい感じの方法がありました。

stackoverflow.com

this.constructor 経由でstaticプロパティを呼び出す関数を実装しておく方法です。
実装はこんな感じになります。

abstract class MoneyBase {
  static readonly CurrencyUnit: string
  readonly amount: number

  protected constructor(amount: number) {
      this.amount = amount
  }

  get CurrencyUnit() {
      return (this.constructor as typeof MoneyBase).CurrencyUnit
  }
}

class JPY extends MoneyBase {
  static readonly CurrencyUnit: string = 'Yen'

  constructor(amount: number) {
    super(amount)
  }
}

class USD extends MoneyBase {
  static readonly CurrencyUnit: string = 'Dollar'
 
  constructor(amount: number) {
    super(amount)
  }
}

const usd: MoneyBase = new USD(100)

console.log(usd.CurrencyUnit)
// "Dollar"
console.log(USD.CurrencyUnit)
// "Dollar"

インスタンス経由からも、クラスからも無事staticプロパティを呼び出すことに成功しました!

おわりに

議論の余地はありそうではありますが、とりあえずは実装できました。
こうやったらもっと良いよ!とかあれば、教えていただけると嬉しいです!

【スクラムの実験カタログ】ふりかえりを変えてみる

はじめに

メーカーのコーポレート部門でソフトウェアエンジニアとスクラムマスターをやっているモンゴルです。
スクラムでの実験の中で良さそうなものを紹介していきたいと思います。

第二回目はふりかえりを変えるです。

ふりかえりを変えるって、何を変えるの?

ふりかえりの手法自体を変えてみる

次のSpeakerDeckの資料が参考になります

speakerdeck.com

チームメンバーそれぞれが感じる課題というのは異なるので、どれをやってみるといいか話し合ってみるといいでしょう。
対話によって、新たにやってみるふりかえりの目的意識も共有できて、ふりかえりの質が高くなると感じています。

また、「意見が出ない、、」ということであれば、未来志向のものを提案してみるといいでしょう。
KPT等、通常よく実施されるふりかえりは過去を見つめて意見を出し合います。
未来志向で、ありたい姿を考えることにより、自分たちを今までとは異なった視点、俯瞰した視点で見るきっかけにもなります。

むきなおり(=未来志向のふりかえり)について、次の記事なども読んでおくといいと思います。

ふりかえりのファシリテーター(以下、ふりかえりマスター)を変えてみる

チームのふりかえりの雰囲気が変わったり、チーム全体のファシリテーション能力向上のきっかけになる効果があります。
ただ任せるだけでなく、スクラムマスターとしてふりかえりマスターへフィードバックもすることも重要です。

どういうチーム、ケースにおすすめの実験か?

  • ふりかえりに慣れてしまって、新たなTryがなかなか見つけられないチーム
  • チーム全体でファシリテーションのスキルを向上させたいチーム

おわりに

個人的には、むきなおりがお気に入りです。
3ヶ月、半年に1度やってみるといいと思います。

みなさんも、ぜひ、「ふりかえりをこう変えたら良かったよ」とか「このふりかえりを定期的にやるの効果あるよ」とかあれば、教えていただけると嬉しいです!

【スクラムの実験カタログ】1dayスプリント

はじめに

メーカーのコーポレート部門でソフトウェアエンジニアとスクラムマスターをやっているモンゴルです。
スクラムでの実験の中で良さそうなものを紹介していきたいと思います。

第一回目は1dayスプリントです。

1dayスプリントって何?

その名の通り、スプリントのタイムボックスを1日にして、スクラムイベントを実施する実験です。
実験の延長で、実際に自分たちの取り組みに取り入れてみてもいいと思います。

1dayスプリントどうやるの?

タイムスケジュールを事前に決めます。
タイトになりがちなので、おおよそのスケジュールを事前に決めておき、前日に翌日の予定を確認してFIXするようにするといいでしょう。

タイムスケジュールの例としてはこんな感じになると思います。

  • 9:30~10:00 プランニング
  • 10:00~12:00 作業
  • 13:00~13:30 リファインメント
  • 13:30~16:00 作業
  • 16:00~16:30 スプリントレビュー
  • 16:30~17:00 ふりかえり

どういうチーム、ケースにおすすめの実験か?

  • 1w/2wスプリントに慣れてきて刺激が欲しいチーム
  • モブ作業、ペア作業、コミュニケーションを増やしてみたいチーム
  • 長期連休があり、いつもと同様のタイムボックスが確保できない場合

1dayスプリントで気づけることの例

  • コミュニケーションを密に取ることで、フロー効率が上がること
  • 1,2日放置されているタスクがなくなり、普段自分たちのコミュニケーションやタスク管理の問題点に気づける

その他

  • プランニングからレビューまでの時間が限られているので、集中して取り組む & コミュニケーションを増やす必要があり、疲れる
  • だけど、一日でレビューまで完了して、残業ブーストで対応するという技は使えないので残業は減る

おわりに

「自分たちはこんな感じでやってるで!」とか、「こういう実験やってるよ!」とかあれば、是非教えてください。
引き続き、スクラムの実験を紹介していこうと思います!