読者です 読者をやめる 読者になる 読者になる

アニメイトラボ開発者ブログ

株式会社アニメイトラボの開発者ブログです


アニメイトラボ開発者ブログ

developer.animatelab.com


アニメイトラボ流エンジニア日報と、個人的に始めてみたプライベート日報

抱き枕の人ことバトルプログラマー柴田智也 id:bps_tomoya です。

みなさんは日々の業務で日報を書いているでしょうか。ひょっとすると、「日報なんて」と思われる方もいらっしゃるかもしれません。書くのがメンドウ、書いても読まれたのか読まれてないのかよく分からない、作業時間に当てた方が有益だ…日報を書くことには色々な意見があると思います。

それでも弊社、アニメイトラボのエンジニア陣は esa.io 上で出社時に日報を作成、退社時に更新することを日課としています。

f:id:bps_tomoya:20160831182240p:plain

アニメイトラボ流エンジニア日報

アニメイトラボの日報の主な目的は、メンバー間で以下のことを共有するためです。

  • 今朝はどんな気持ちですか
  • 今日なにやる予定?
  • どんな成果が出せましたか
  • 今日はどんな気持ちでしたか

「今朝はどんな気持ちですか」「今日はどんな気持ちでしたか」というのは、一般的な日報ではあまり見られないものかもしれません。 他の項目についてでもですが、アニメイトラボの日報は特にかしこまって書くものではなく、各メンバーが思うまま、カジュアルに記載できるような場を心がけたものになっています。

例えば私の日報だと、最初にこんな気持ちを書いて、それから今日の予定…成果…と続けています。

f:id:bps_tomoya:20160831181448p:plain

「どんな成果が出せましたか」については、コマンドを叩くだけで GitHub での活動状況を列挙形式でズラッと取得できる、ペパボさんの pepabo/furik というものがあります。

github.com

これをベースに弊社 CTO id:bash0C7 が、Ruby に慣れてない人でも扱えるように make コマンドで利用できるように改造した animateLAB/diary というツールを利用しています。

github.com

f:id:bps_tomoya:20160831183924p:plain

これをコピペして貼り付ければ、「えーと…今日はこの Issue を立てて…こっちは Close して…そうそう夕方には PullRequest を出したんだっけ…」と今日の貢献を1つ1つ確認する時間が、数分間から数秒にギャッと圧縮することができます。

また esa.io で管理された日報なので、カジュアルにスターを付けたりコメントを書き込んだりすることもできます。

タスクの予定や消化具合の共有はもちろんのことですが、一緒に働くメンバーやマネージャー層がもっとも知りたいのは「みんな元気に働けてるかな?」ということではないかと思います。

もしも元気でない、何か問題などが起きているのであれば、上記のような気持ちを書く気持ちにはなりにくいと思います。そういう面で見てみると、弊社の日報はメンバーの様々な角度から見た「健康診断」の意味合いも持ち合わせているかなと感じています。

個人的に始めたプライベート日報

ここ1ヶ月、id:r7kamura さんが運営されていらっしゃる 日報 をお借りして、プライベート日報という試みをしていました。 その日1日の自分の行動や思っていたこと、ザックリとした知見をアウトプットする1人実験です。

f:id:bps_tomoya:20160831181904p:plain

私は個人ブログも持っていますが、あえて別の場でプライベート日報を書くようにしてみたのは以下の理由によるものです。

  • 個人ブログはあくまでも技術知見主軸のアーカイバとしたい(たまに雑記も書きます)
  • 上記の理由から、日報で技術知見記事が埋もれるのは好ましくない
  • 「皆で寄り合って書く日報」というコミュニティについて純粋に興味があった

プライベート日報を始めてみて

あまり深い考えをもたずに始めて見たプライベート日報ですが、思いのほかプライベート日報でアウトプットしたこと、またその行動が業務にもよい影響を与えることがありました。

弊社では 1on1 という、社員と上長が1対1で雑にお喋りする時間を設けています。このお喋りの中でプライベート日報の内容を話題にしてみると、そこで書いていた考えを業務に取り込める機会に恵まれたり、ふわっとしたことをプライベート日報を書くことで「あ、次の 1on1 でこれ話したいかな」という自分自身のふわっとしていた部分をすくい上げることができました。

1日を総括、アーカイブするのはやってみると意外と楽しいですし、自分にとってはストリーミングな Twitter と対をなすツールかな? と感じながら日々のプライベート日報を書いています。

今回は弊社アニメイトラボ流エンジニア日報と、バトルプログラマー柴田智也が個人的に始めてみたプライベート日報をご紹介させていただきました。 皆様の日報ライフのご参考になれば幸いです。

Android で一部の文字列をリンク化した TextView を生成するクラスを実装してみました #Kotlin

抱き枕と戯れる人生を謳歌するバトルプログラマー柴田智也 id:bps_tomoya です。

Android アプリケーション開発をしていると、一部の文字列をリンク化したテキストを表示したいという場面があると思います。 私も例に漏れずそういったシーンに遭遇したので、ひょっとするともっと簡単な実装ができるのかもしれませんが、独自のクラスを実装してみました。

このクラスは、

  • こちら(URL A のリンクを設定する)
  • こちら(URL B のリンクを設定する)

のようにリンク化対象文字列が重複してしまった場合にも、それぞれにそれぞれのリンクが設定されることを考慮したクラスになっております。
また基礎的な実装のみに止めているため、メソッドに渡す引数などは状況に合わせて実装する必要があることにご留意ください。

検証環境

  • Android 5.1 (HTC Desire 626)
  • Kotlin 1.0.3

コード(Kotlin)

/**
 * 一部の文字列をリンク化した TextView を生成するクラス。
 * Activity から独立したクラスなので、context を受け取ってインスタンス化されます。
 */
class TextViewWithHyperLinkBuilder(context: Context) {
    private val context: Context by lazy { context }

    /**
     * 文字列の一部をリンク化した TextView を返却する。
     */
    fun getTextViewWithHyperLink(): TextView {
        // 対象文字列。
        val contentText = "サイト1はこちら! サイト2はこちら!"

        // リンク化対象の文字列と URL マップ。
        // キー重複の可能性を受容できるようにキーは整数値を割り当てています。
        // また、この後の処理で順序保証が必要となる観点から TreeMap を利用します。
        val map = TreeMap<Int, Map<String, String>>()
        map.put(0, mapOf("こちら" to "https://www.animatelab.com/"))
        map.put(1, mapOf("こちら" to "http://developer.animatelab.com/"))

        // 文字列の一部をリンク化する処理を呼び出し、返り値を TextView に格納する。
        val spannableString = this.createSpannableString(contentText, map)
        val textView = TextView(this.context)
        textView.text = spannableString
        textView.movementMethod = LinkMovementMethod.getInstance()

        return textView
    }

    /**
     * リンク化するべき文字列の一部の範囲を探索し、タップイベントを設定した文字列を返却する。
     */
    private fun createSpannableString(message: String, map: TreeMap<Int, Map<String, String>>): SpannableString {
        val spannableString = SpannableString(message)
        val prevFindEndHistory = HashMap<String, Int>()

        map.entries.forEach { e ->
            val element = e.value.entries.elementAt(0)
            val pattern = Pattern.compile(element.key)
            // 前回の探索で一致した箇所の end 履歴を取り出します。
            // その値を使って対象文字列を substring したものを pattern.matcher に渡すことで、
            // 前回探索した範囲を探索対象から除外します。
            val prevFindEnd = prevFindEndHistory[element.key] ?: 0
            val matcher = pattern.matcher(message.substring(prevFindEnd))
            var start = 0
            var end = 0

            while (matcher.find()) {
                // 探索一致箇所の start と end は元の対象文字列に対する値としてはズレが発生してしまいます。
                // substring した文字数ぶんだけズレが発生しているのでprevFindEnd を加算します。
                start = matcher.start() + prevFindEnd
                end = matcher.end() + prevFindEnd
                break
            }

            // 今回の探索で一致した箇所の end 履歴を格納します。
            prevFindEndHistory.put(element.key, end)

            // 対象文字列のリンク化するべき範囲にイベントを設定します。
            spannableString.setSpan(object: ClickableSpan() {
                override fun onClick(textView: View) {
                    val url = element.value
                    val uri = Uri.parse(url)
                    val intent = Intent(Intent.ACTION_VIEW, uri)
                    context.startActivity(intent)
                }
            }, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
        }

        return spannableString
    }
}

生成された TextView を Activity に表示すると、このような結果になります。

f:id:bps_tomoya:20160805133231p:plain:w300

1つめの「こちら」をクリックするとアニメイトラボのサイトが、

f:id:bps_tomoya:20160805132358p:plain:w300

2つめの「こちら」をクリックするとアニメイトラボ開発者ブログが WEB ブラウザで開きます。

f:id:bps_tomoya:20160805132405p:plain:w300

ぜひ参考にしてみてください!

「週末54時間の起業体験」Startup Weekend Ogaki 03にコーチ参加します

古きよき時代から来ました、まじめなSE、まじめにSE。 CTOの id:bash0C7 です。

7/29(金)〜31(日)の3日間行われるスタートアップ体験イベントStartup Weekend Ogaki 03にコーチの一人として参加します。

swogaki.doorkeeper.jp

中部地方に縁のある方はもとより他府県の方もぜひご参加ください。

前回の様子

f:id:bash0C7:20160715013135p:plain *1

Startup Weekend OgakiのFBページでの過去開催の写真を見てイメージと期待を膨らませましょう。

Startup Weekendとは

Webサイトでこのように説明されています。

nposw.org

“スタートアップウィークエンド(SW)”は、金曜夜から日曜夜まで54時間かけて開催される、「スタートアップ体験イベント」です。週末だけで参加者は、アイディアをカタチにするための方法論を学び、スタートアップをリアルに経験することができます。 わたしたちは、スタートアップが最初の一歩を踏み出すためのプラットフォームを目指しており、開発者やビジネスマネージャー、アントレプレナー、デザイナー、マーケター等、さまざまなスキルの人々を結びつけ、アイディアが現実になることを願ってます。

2007年アメリカ発祥のイベントで、日本では2009年の初開催以来全国様々な都市で開催されています。

Startup Weekend Ogaki 03とは

岐阜県大垣市でのStartup Weekendです。

大垣といえば古くから交通の要衝として大変栄えた街ですが、昨今ITに大変力を入れており、IT研究開発の拠点ソフトピアジャパンや、IAMASこと情報科学芸術大学院大学がとくに有名です。

今回、大垣では初の夏開催で、2日目と同日(7/30)に大垣花火大会が開催予定ということもあり、最高の夏を送ることができます。

swogaki.doorkeeper.jp

大垣とわたし

会社紹介ページにあるわたしの略歴に記載している通り生まれも育ち関西なのですが、実はこの大垣はわたしのエンジニア人生の中で大変恩義と思い出の深い街です。

2003年に大学を卒業し大阪のSIerに入社し、一番最初にアサインされたプロジェクトの場が大垣でした。初の実務、初の出張、初のホテル暮らし*2、初のカットオーバー立会い、お客様との共同作業、打ち上げなどなど、様々なことを体験しました。 当時はメインフレームを使った基幹業務システム開発に従事していたので、今のアニメイトラボとでは技術としては全く使っているものは違いますが、そのプロジェクトで叩き込まれたエンジニアとしての振る舞いや基礎の考え方は完全に今の自分のベースになっています。

そんな思い出深い大垣の地で、コーチの一員としてStartup Weekend Ogaki 03のサポートを担えるのは、大変感慨深いです。よろしくお願いします!

お申込み方法

下記サイトからお申込みください!

swogaki.doorkeeper.jp

大垣での初プロジェクトから今までのわたしのキャリアについて興味を持った方は....

8/3(水)の晩、東京・渋谷でのこのイベントでじっくりお話します。ぜひご参加ください。参加費無料です。

careerlog.doorkeeper.jp

予め、先日掲載いただいた下記のインタビューをご覧いただくと、当日120%楽しめるかと思います。

careerlog.jp

careerlog.jp

*1:https://www.facebook.com/swogaki/posts/505697909630208 より

*2:大垣駅前のビジネスホテルが定宿でした