半空洞男女関係

思ったこととかプログラミングしてるときのメモとか色々かいてます。メールはidそのままgmail

うちのチームのデイリースクラム 2021年夏編

を見ていて、うちのチームのデイリースクラムを紹介したくなったのでかいてみます。こういうのを書くのははじめてかもしれない。

全体デイリースクラム

まず、決まった時間になったら一つの部屋に集まって、全体のデイリースクラムをする。今は3チームくらいあるので、全体でやりとりしたいことも多い。 全体のゴールとかあるわけでもないので、ただの朝会って感じ。(「朝会」でいいのかも) チャットで報告でおしまいでもいいのだが、「知らなかったー」とかはあるので、共有したい勤怠の連絡事項とか、今日はリリースがありますねーとか、この前の障害についてですがー、などなど、全体で知っておきたい情報はここで共有する。

現状、品証チームが各チームに入る形ではなくて、横串サポートチーム的にいるので、横断した進捗の報告とかはここでしてしまう。(まだスプリントごとにテストはできていないとか、色々テスト周りの課題はある。絶賛改善中。)

チームのデイリースクラム

各チームでちょっとずつ文化が違ったりすると思うので、隣のデイリースクラムがどんな感じかは知らないんだけど、自分が所属してるチームの様子。今のチームは自分がリーダーをしていて、司会とかも自分がやっているんだけど、今はリーダーを後輩に引き継ぎ中で、自分は見守る立場にいる。

なお、このデイリースクラムは、15分の枠をとっている。

ダッシュボードで、大まかに確認

f:id:mactkg:20210808173647p:plain
頑張って描きました よく見たらスプリント終盤なのに2つもチケット着手してない!

まずは、みんなでスプリントのダッシュボードを見る。ダッシュボードにはスプリントのバーンダウンチャートや、見積もりよりもかかってるタスクの一覧、残余が残ってるのにDONEになってるタスクの一覧とかがフィルターで表示されている。これらを見ながら、ダッシュボードをちょっとメンテしたり、困ってるタスクのざっくり把握、バーンダウンチャートが正常にバーンしてそうかの傾向をつかむ。(ちなみに、自分のいるチームは時間見積もりをしている)

ゴールの確認

その次に、デイリースクラムScrapboxページに書かれたゴールを上から確認していく。「このゴールのタスク、取ってた人、今どんな感じ?」というやりとりをして、「終わりましたー」「今やってますー」とか、「今レビューで止まってるんで、みなさんレビューしてください」とか、「ちょっと困ってるんですよね... DSの後とかどこかでペアプロお願いしていいですか?」とかやりとりしていく。ここまで話すと、大体もうその日やることや困りごとはみんな話せている。

(なお、今はいわゆる"Feature Factory"に近い感じになってしまってるんで、ストーリーが終わったら受け入れ条件を確認して、とか、そういう素敵な仕組みにはできてないです。あしからず)

ゴールを確認しながら同時に、「このゴール、達成できそうかなあ?」っていう話もメンバーとする。この時、自分は結構悲観的に考えることを心がけている。心配事があれば、質問をする。「でもさ、ここでレビュー盛り上がったりしないの?」とか、「このタスクって、他の人のタスク終わってないとできないとかない?」とか、「こっちのゴール優先しちゃったら、あっちのゴールがおわんなくない?どうしようっか。」とか、そんな感じ。たまに「うーん、これだと終わらないな・・・。」ということもあるので、その場合はタスクやゴールをトリアージしたりもある。

その他、チームメンバーの共有事項

その後は、各チームメンバーからの共有事項。チームのデイリースクラムScrapboxページはスプリントごとに新しく作っていて、毎日日付を書いてその下にメンバーごとの共有事項を書く欄を作ってる。これは事前に書いておく決まり(話しながら書く人もいる)。この場で、改めてPRレビューのプッシュだったり、仕事の相談事や、今日やる特別なこと、細い勤怠連絡などの共有もここでする。

もうタスクなくなりましたー。とか、依存の関係で着手できないんだよね。とかがあれば、ここで調整したりするかなあ。本当に順調すぎる場合は、次のバックログアイテムを取ったりしている。今のチームは「完了できないなら落とせ」を原則にしているので、大体スプリント終盤は次のアイテムを着手したり、ちょっとした改善をしていることが多い。遅れてるタスクを巻き取るのにも使えるし、この原則は結構ワークしています。

最後、ゴール達成自信度の記載と、対策記載

うまくいっていたはずなのに、気づいたらスプリント終盤に爆弾があって、それに気づけなくてゴール達成できなかったとか、やばいのわかっていたけど対策が取れずにゴール達成できなかったというふりかえりがあったので、最後にゴール達成の自信をチームで決めることにしている。自信があればある。それ以外はないって書く。ない場合は、どうやったらゴール達成の自信を取り戻せるかを書く。デイリースクラムのまとめみたいな感じ。

あと、前日の対策が実施できたかも確認している。結構差し込みがあって、「そういえばできなかったなあ」というのもある。この辺りは、忘れないようにテンプレートがあるって感じ。

雑談

最後に、雑談タイムを最近はしてる。日替わりで、なんか適当に仕事の話とか休みの話とか話す時間。新しい人も入ったので、こういう工夫をしたりはしています。まあどこも色々してるよね。

最初からこんなにもりもりだったわけじゃないよ

最初は、よくある感じでそれぞれが「昨日やったこと」「今日やること」「困ってること」を話す感じだった。だけど、ゴール達成できなかったり、「なんか最後わちゃわちゃする」と言ったような発見がふりかえりであったので、ちょっとずつ工夫を足していった感じ。

色々やりすぎた工夫もあって、チームが成長すれば、「今はもういらなくない?」っていう工夫もあるはず。誰かのチームにとっては「そんなのやんなくていいじゃん」もあれば、「それいいね!」もあるはず。大事なのはチームの現状をしっかり認識して、ちょっとずつみんなで工夫していくことだと思います。

最近の悩み

最近は、結局のところリーダーがよく喋ってしまう感じがして、みんながもっと喋った方がいいのかなあ、これでいいのかなあ?というところ。個別にOOさんどうぞ!とか振っていくという手段もあると思うのだが、結構進捗報告っぽくなりがちで、ゴール意識した会話ができなくなりがちだったりするし。なんかこの辺うまくやれてんなーという人がいたら教えてください。まあこれも、チームで課題感がなければそれでいいとは思うんだけど。

皆さんのプロダクト開発でも、うちはこんなことやってるよーというのがあれば教えてください。

enumはswitchingのために使い、値として使うのであれば、structにするのが良い

2017年の記事。

matt.diephouse.com

enumを使って分析用のイベントを表現するケースが記事だと出てくる。IDだけなら良いけど、メタデータとか、他にも付与したい情報が出てくるが、structで表現するともっと改善できるよ。と書いてある。

extension AnalyticsEvent {
    var name: String {
        switch self {
        case .loginScreenViewed, .loginAttempted,
             .loginSucceeded, .messageListViewed:
            return String(describing: self)
        case .loginFailed:
            return "loginFailed"
        case .messageSelected:
            return "messageSelected"
        case .messageDeleted:
            return "messageDeleted"
        }
    }

    var metadata: [String : String] { … }
}

enumは何かを網羅するのには便利だと思うけど、分析用のイベントは別に網羅したいわけではない。

今回の例だとstructはイベントごとに個別に定義して、情報を受け取るためのprotocolを用意するのかと思っていた。けれども、イベントを表現するstructを作り、initメソッドを隠蔽する代わりに、structを得るためのメソッドやプロパティを生やしているという感じだった。

struct AnalyticsEvent {
    var name: String
    var metadata: [String : String]

    private init(name: String, metadata: [String: String] = [:]) {
        self.name = name
        self.metadata = metadata
    }

    static func loginFailed(reason: LoginFailureReason) -> AnalyticsEvent {
        return AnalyticsEvent(
            name: "loginFailed"
            metadata: ["reason" : String(describing: reason)]
        )
    }
    static let loginSucceeded = AnalyticsEvent(name: "loginSucceeded")
    …
}

方式はなんでもいいと思うんだけど、この形式にすると分析ログを送信する際にどういう情報が必要なのかが明らかになって良いなと思う。

ここ一年くらい品質やテストについて考えながら仕事をしている中で、値の網羅性を担保するというのはめちゃめちゃ大事だなと思って網羅という言葉がキーワードになりつつある。

追記

この記事に対するレスポンスでDave Delongという人が別の提案をしている記事を見つけた。protocol使えばよくて、enumでも、structでもなんでも好きにできるよと。

davedelong.com

Kindleでライセンスの上限に達してしまった場合の対処法: 端末とアカウントのリンクを解除する

Kindleは6端末までしか同時に本をインストールできないので、何年も使っていると、古いマシンや使っていない携帯にKindle本が入ったままになっていて、よく参照したい本はライセンス上限に到達してしまう。

前はちまちまアクセスできる端末を立ち上げて本を削除していたのだけど、それでも解決できなかったことがあったのでやり方を調べた。最終的には、端末とアカウントのリンクを解除すれば良い。

アカウントサービス > コンテンツと端末の管理 > Kindle > 端末 に飛んで、使わなくなったデバイスと登録の解除をすれば問題ない。

https://www.amazon.co.jp/hz/mycd/digital-console/devicedetails?deviceFamily=KINDLE_APP

バイス詳細画面に入って、本を削除してしまうと、そもそもの本自体がアカウントから削除されてしまうみたいなので注意した方がいい。