コネヒト開発者ブログ

コネヒト開発者ブログ

Kotlinを導入したお話

f:id:tommy_kw:20161106193050p:plain

こんにちは!エンジニアの富田(@tommykw)です。 ママリQ Android アプリにKoltinを導入しましたので、導入方法などを紹介します。

ママリQ Android アプリ

家族の毎日の疑問や悩みを解決するママのためのQ&Aアプリです。ストアのレビューが4.5と非常に評価の高いアプリです。

なぜKotlinを導入したのか

  • Javaだと冗長、複雑になるコードもすっきり可読性が上がる
  • Swift使いのiOSエンジニアにもなじみやすい文法
  • JavaのNullPointerExceptionを駆逐できる
  • デメリットが少なかった

簡潔に安全にコードを書けるのはいいですね。Kotlinのスコープ関数やreadonlyや強力なコレクションを言語標準機能として使えるのはとても魅力的なため導入に踏み切りました。

ただメリットだけではなく、懸念点もありました。 DataBindingを利用すると真っ赤な画面での開発になり辛いです。

f:id:tommy_kw:20161107075432p:plain

KotlinとDataBindingを使っている環境であればこのような画面で開発されていると思いますが、JetBrainsのKotlin Issueでversion 1.0.5で修正となっていますね。やったね!! 今後は快適に開発が進められそうです。

導入内容について

それぞれ内容について説明します。

導入方針策定

Kotlin化については以下の基本方針を基に進めました。

  • 無理にKotlin化はしない
  • リファクタリングや新機能を実装する際にKotlin化をする
  • テストはKotlinで書いてみる

コネヒトは開発者の人数も少なくリソースが限られているため、無理にKotlin化するのではなく、リファクタリングなど最低限の部分でKotlinを導入しています。

Kotlin version 1.0.4

Kotlinをプロジェクトに導入するのは非常に簡単です。 Android Studio > Tools > Kotlin > Configure Kotlin in Projectをクリックすればダイアログが出て、OKを押すとセットアップできます。コネヒトでは現在最新版のversion 1.0.4を導入しています。

kotlintest テストフレーム

ユニットテストでkotlintestを使っています。テストフレームはspekなどもありますが、kotlintestはscalatestのような記述でmatcherも豊富でこのライブラリだけで簡単にテストが書けるため採用しました。以下はkotlintestを使ったサンプルになります。

/**
 * 日付に関するテスト
 */
class DateTest : StringSpec() {
    init {
        "Date型からyyyy年MM月dd日形式に変換する" {
            DateUtil.toDisplayString(Calendar.getInstance().apply {
                set(2016, 11, 2)
            }.time) shouldBe "2016年11月2日"

        }
        "Date型からyyyy-MM-dd形式に変換する" {
            DateUtil.toPostString(Calendar.getInstance().apply {
                set(2016, 11, 2)
            }.time) shouldBe "2016-11-2"
        }
    }
}

アノテーションを使う

JavaとKotlinが共存するプロダクトなのでKotlinからJavaを呼び出すこともありますし、その逆も然りです。クラッシュ予防や簡潔に呼び出すためのアノテーションを使いました。

  • @Nullableアノテーション
class TestActivity : AppCompatActivity(), TextView.OnEditorActionListener {
    override fun onEditorAction(v: TextView, actionId: Int, event: KeyEvent): Boolean {  // java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter event
    }
}

上記のコードはKeyEventがNonnullのため実行時にクラッシュします。これはNonnullな型に対してnullがセットされたため発生するクラッシュです。このようなクラッシュが起きた時はエラーだけを見てもどこでエラーが発生したか分かりにくいです。 この不具合を回避するためにはJava側では@Nullableアノテーション、Kotlin側では?を使ってNullableであることを宣言する必要があります

  • @JvmStaticアノテーション
// Kotlin
TestFragment : Fragment() {
    companion object {
        @JvmStatic
        fun newInstance(): TestFragment {
            return TestFragment()
        }
    }
}

// Java @JvmStaticあり
TestFragment.newInstance()
// Java @JvmStaticなし
TestFragment.Companion.newInstance()

シングルトンオブジェクトをクラス内に定義するには、companionキーワードを使い、 companion付きのオブジェクトをcompanionオブジェクトと言います。 通常はcompanionオブジェクトを介して呼び出しますが、 上記のコードはアノテーションを使うことによって直接メソッドを呼ぶことができます。

  • @JvmFieldアノテーション
// Kotlin
class Member {
    @JvmField
    var id = 0
    @JvmField
    var name = ""
}

// Java
Member member = new Member();
member.id
member.name

上記のコードはPOJOにgetter/setterを生やしてプロパティを呼び出しますが、@JvmFieldを使うことによってgetter/setterではなく直接プロパティにアクセスできます。

Kotlin/Javaでそれぞれ問題なくアクセスできるので安心して導入できますね

簡単に導入結果について

  • 1ヶ月で10%くらいはKotlin化できた
  • Kotlinリファクタリングで1、2割くらいコード行数が減った
  • コレクション操作が直感的で扱いやすかった
  • val(readonly)、var(mutable)があり、readonlyがあるので安全だった
  • 遅延初期化(lateinit/lazy)が便利だった

導入が本当に楽でした。コード行数が減ったのはスコープ関数やSAM変換を使うことによって無駄なimportも減り短く記述できたからです。 valはJavaでいうfinalに近い存在だと思いますが、valはimmutableではなくあくまでreadonlyになるのが興味深かったです。実際に使ってみてreadonlyとスコープ関数と遅延初期化は非常に便利でしたし、可読性も上がり安心してコードを書くことができました。lateinit/lazyについては以下の通りです。

  • lateinit
class TestActivity : AppCompatActivity() {
    private lateinit var binding: ActivityTestBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_test)
    }
}

lateinitは必ず初期化するけどクラス生成時に初期化できないようなケースで使用します。必ず初期化するのでNonnullであることを保証し、面倒くさいNullチェックが不要となります。

  • lazy
class TestActivity: AppCompatActivity() {
    private lateinit var binding: ActivityTestBinding
    private val header by lazy {
        DataBindingUtil.inflate<HeaderBinding>(
            layoutInflater,
            R.layout.header,
            binding.headerList,
            false
        )
    }
}

lazyは対象の変数にアクセスされた際に初期化されます。遅延初期化によって効率的に初期化され、readonlyにできるのが素敵ですね

まとめ

ママリQ AndroidにKotlinを導入したお話でした。まだ導入して1ヶ月のため理解も浅く知見も少ないですが、今後KotlinやOSSに対して何かしら貢献できればと考えています。

最近のKotlin界隈では、TornadoFXRxKotlinFXAnkoなどAndroidに限らず面白いフレームが多く刺激的ではないでしょうか。version 1.1からasync、await、yieldも導入されてますます楽しみですね!

速いらしいのでYarnを使ってみる

f:id:dachi023:20161015111905p:plain

こんにちは。フロントエンジニアの安達 (@ry0_adachi) です。
最近、一気に冷え込んできたのでしっかり着込んで出かけないと痛い目を見そうです (1敗)。

さて、今回はYarnをさっくり触ってみたのでその検証と感想を書こうと思います。

Yarnとは

github.com

JavaScriptのパッケージマネージャーです。
npm, package.jsonとの互換性もあるので従来のプロジェクトでも使えます。
今の所、私の認識としては「npm installを便利にしたもの」という感じ。

メリット

  • インストールが速い
  • lockファイルによるバージョンロック
  • 絵文字が可愛い

あたりでしょうか。絵文字があるおかげでインストール中もほっこりします。
それと、重複したモジュールの整理をしたりもしてくれます。
その辺はまだそんなに触ってないので、今回は本当に速いのかどうかを検証します。

Yarnのインストール

$ npm i -g yarn

npm installとyarn installの比較

せっかくなのでキャッシュを消した状態からmamariのリポジトリで試してみます。
時間計測はtimeコマンド使ってやります。
(検証はモバイルルータ使ってやったのでそもそもがめちゃ遅いです)

npm install

$ rm -rf node_modules
$ npm cache clean
$ time npm i

real    8m1.080s
user    1m23.301s
sys     0m18.123s

遅いですね...。

Yarn

まずはキャッシュない状態から。

$ rm -rf node_modules
$ time yarn

real    3m49.978s
user    0m40.128s
sys     0m18.585s

既に速いですがさらにキャッシュありでやってみます。
Yarnでインストールすると ~/.yarn-cache にグローバルなキャッシュとして残り、
2回目以降のインストールがさらに高速になります。

↓がキャッシュありの場合の検証結果です。

$ rm -rf node_modules
$ time yarn

real    0m15.863s
user    0m10.773s
sys     0m6.903s

驚きの速さ。real timeだとnpm installに比べて7分強縮まってますね。

感想

想像以上に速かったです。CI上で使ってあげたら結構な速度改善ができそうな予感です。
まだ出たばかりなので今後に期待ですが、最初の感想としては素敵!といった感じでした。

参考

「サービス落ちたら電話で通知」を10分で実現・本番に投入する(Pingdom + Pagerduty)

こんにちは、徐々に涼しくなってきた金城@o0h_です。
最近は セブン-イレブンのアボカドとツナのチョップドサラダを食べる時にちょっと幸せを感じています。タンパク質が豊富なアボカドが美味しく摂れるのも素敵です。

さて、突然ですが皆様に於かれましては「提供しているサービスの監視」どうしていますか?
監視対象や項目・方法は色々あれど、運営として最低限防がなければいけないのは「サービスが止まっていた、利用できなくなっていた」という状況でしょうか。うっ!落ちている!! 怖いですね。
死活監視。定期的に「対象の外部からアクセスして」「レスポンスを返せる」というチェックによって、アプリケーションやらデータベースやらネットワークやら・・・というあらゆるレイヤーを一気通貫で「無事そうか」を確認する。
これが通れば「最低限動いている」、もしだめなら・・・いち早く通知を受け取りたい!

コネヒトでは、お盆休みを迎えるのを機に、監視方法を刷新し新システムの導入をしました。
実際の監視から、Slackや電話でプッシュするアラートの発報まで、とてもスムーズに稼働までもっていくことができたのでした。今回はそんな便利サービス紹介させてください。

死活監視を行うPingdom と通知・エスカレーションを行うPagerDuty です。 f:id:o0h:20131109145130j:plain

続きを読む

immutableのメリットとImmutable.jsでのModel定義

f:id:dachi023:20160902200209p:plain

こんにちは。フロントエンジニアの安達 (@ry0_adachi) です。
気付いたら前回の私の記事から2ヶ月が経ちました。時間の流れは早いですね...。

さて、今回はimmutableとそれをJSで実現するためのImmutable.jsについてです。
この記事を通して沢山の方にimmutableについて知ってもらえると嬉しいです。

immutableとは

immutableは元となっているオブジェクトに変更を加えない、加えられない状態です。
また、変更を加える、加えられることをmutableと呼びます。

続きを読む

「JQL」は、mixpanelの抱える1つの限界を打ち砕く夢である

こんにちは、PHPなどを書いている金城 (@o0h_) です。ここ暫くはファミリーマートのリーフレタスと大根のサラダセブン-イレブンの15品目のサラダボウル(和風ドレ)が私の食生活においてヘビロテしています。*1

f:id:o0h:20150214152429j:plain

話は変わるのですが、コネヒトでは、ログの収集+データの分析用途のツールの1つとしてmixpanelを利用しています。

*1:[ちょっと宣伝]コンビニサラダについて一家言ある方を、職種とわず募集しています。 ウォンテッドリーからどうぞ!

続きを読む

小規模PHPアプリケーションをDeployerでサッとデプロイする話

f:id:fortkle:20160728164803g:plain

こんにちは! 東京なのに周辺にポケストップが1つもない田舎に住んでいます、@fortkle です(世田谷公園の徒歩圏内に引っ越したいです)。

さて、みなさんはPHPアプリケーションのデプロイツールに何を使っているでしょうか。
今回コネヒトで Deployer というPHPで書かれたデプロイツールを採用したのですが、なぜDeployerなのかという理由と、実際に使っているおすすめの設定をいくつか共有したいと思います。
※ Deployerのインストール方法や基本的な使い方を知りたい場合は既にインターネット上に良い記事がたくさんあるのでそちらを参考にしてみてください。

続きを読む

新人デザイナーさんのディレクションから学んだコミュニケーションの心得

f:id:connehito:20160711094503p:plain

こんにちは、デザイナーのきよえし(@kiyoe_furuichi)です。

先日、ついにコネヒトデザインチームが結成されまして、チーフデザイナーを担当することになりました! 手探りながらチーフとしての役割を担っていて一番感じるのは、自分でつくるより何倍もつくってもらうほうが難しいということです。日々多くの発見や学びがあるなあと勉強させていただいてます。

今回は、私が新人デザイナーさんをディレクションするなかで、より良いコミュニケーションをとるために実践している"心得"をいくつかご紹介したいと思います。

制作の流れ

まず、デザインを制作する流れとして私たちは以下のように制作を行っています。

  1. タスク依頼
  2. スケジュール調整〜制作
  3. フィードバック
  4. リリース・振り返り

私が担っているものは具体的に、タスクの依頼を受けて担当デザイナーを決めることと、スケジュール管理・フィードバックを行いながら完成までフォローをすることです。 最終的なチェックはディレクターさんが行うので、なるべく手戻りが無いようクオリティの担保を行っています。
そんな役割から学んだコミュニケーションの”心得”を、それぞれのフェーズごとにまとめていきたいと思います。

1. タスク依頼 の心得

依頼するタスクはユーザーさんにとってどのようなインパクトがあるのかを伝えること

依頼するにあたって一番気をつけないといけないなと思うのは、単に"タスクをこなす"という意識を持たせないようにするということです。このタスクはなぜ必要なのか、どんなユーザーさんにどんなインパクトを与えられるのかといったところまでを想像してデザインに落とし込めるように、背景から内容までしっかり伝えるようにしています。
そのために行っていることは、依頼を文字に落として伝えるようにしています。口頭では表現でのズレが起こりやすいのでなるべく文字化して伝えるほうが良いと思っています。
最初は文字に落とすことに手間がかかるし省いたほうが良いと思っていましたが、これによって制作途中の大きな手戻りが少なくなりました。担当者がしっかりタスクの内容から想像して意図を持ったデザインが行えているためです。

2. スケジュール調整〜制作 の心得

自分の見積もり工数 + バッファをとった工数でスケジュールを立てること

スケジュールは担当デザイナーさんと一緒に立てていきます。どのくらいで制作できるかを見積もってもらい、それにバッファを足した工数でスケジュールの締め日を決めます。バッファを取るのは、万が一手戻りがあった場合の修正で締め日に間に合わなくなることを防ぐためです。
私自身、自分の工数の見積りは慣れないうちはとても難しくズレが起こることが多々ありました。はじめのうちはバッファを多めに取って、見立てが合うようになるまでの補助として持っておくのが良いと思います。

締め日を決めて、逆算して細かくスケジュールを切ること

締め日が決まったら、さらに逆算してスケジュールを立てていきます。
例えばwebサイトにバナーを掲載するタスクなら、バナーのラフ案はいつまでに上げるか、バナーの制作の期限、バナーをサイトに掲載する実装や実装したコードをレビュワーに確認を取る期限はいつまでか、などです。
細かく決めておくことによってスケジュールの巻きや遅れがより明確になり、締め日までのズレが少なくなります。スケジュールの流れを意識して着手してもらうように、切ったスケジュールはカレンダーで管理をしてリマインドを行ってあげるなどでフォローします。

3. フィードバックの心得

制作物に対してのフィードバックをする際の心得です。

まず、肯定すること

タスクの意図を想像して制作していただいた制作物をもっとより良くするためのフィードバックとなるように、まずは肯定するようにします。
フィードバックは"修正"ではなく"改善"であると考えていて、これは私の経験が大きいのですが指摘をいくつも言われる前にまず「基本良いと思います。」の言葉があるだけで、ポジティブな気持ちでフィードバックを受けることができます。マイナス点の指摘ではなく、その制作物をもっとより良くするためのフィードバックをすることがデザイナーさんとのより良いコミュニケーションにはすごく大切だと思っています。

f:id:connehito:20160710181153p:plain

なるべく文字化すること

フィードバックにおいても、タスクを依頼する際と同じようになるべく制作物のフィードバック点は文字に起こすようにします。あとから読み返せるという点と、口頭で伝える時の言葉のニュアンスによってズレがないようにするためです。(もちろん口頭でも補足は行います)
また、担当デザイナーさんに意図を説明していただくときも文字化してもらい、制作物のロジックを確認し、しっかりユーザーファーストに考えて制作できているかを見るようにしています。
文字化にすることが良いかどうかはフィードバックの内容や場合によって変わりますが、基本的にはフィードバックの回数が減ったり、同じようなやりとりを何度もすることがなくなりました。

答えは言わず、考えてもらうようにすること

フィードバック点は"こうすればいいよ"という答えではなく、答えまでの道筋を伝えるようにします。
初めのうちはもどかしいこともありますが、思考してもらうことが次の学びに繋がると思うのでなるべくそうするようにしています。例えばカラーリングのフィードバックの場合、その配色・トーンから感じる印象はそのクリエイティブの意図したい印象と合っている?どういった配色にするともっとユーザーさんに意図が伝わるか?といったようなフィードバックを行っています。

4. リリース・振り返り の心得

労いの言葉は必ずかけること

完成やリリースをしたら全力で”おつかれさま!”の言葉を伝えます。これは社内全体でそういった文化があり、リリースをした際に周知するSlackのチャンネルにて、みんなでその方の頑張りを労います。
f:id:connehito:20160711103012p:plain

見積もり工数と実工数との差分は必ず振り返ること

見積もってもらったスケジュールの反省は必ず行います。初めのうちはスケジュールの見積もりは上手く行くことが少ないです。次に生かしていくために、見積もっていた工数と実工数の比較とどこに時間がかかってしまったのかを振り返り、見積もりの精度を上げていきます。
ここでなるべく細かく振り返りができるように、都度感じたことを都度メモを取っておくようにしています。

メモ
【◯◯特集記事のバナー作成】
・制作のスケジュールから +0.5 取っての完成
・写真の選定で +0.2〜3 ほど時間を取っていた
・配色のフィードバックが多かった、修正で +0.3 ほど時間を取った

[改善するには]
・写真選定の時間を短縮したい -> 写真素材の探し方のアドバイスをする
・セレクトしてもらった写真がバナーに使いづらそう -> 写真の選び方のアドバイスをする
・フォントの選定・文字組みに苦手意識がありそう -> 参考になりそうなバナーのインプット時間を多めに取ってもらう


まとめ

いかがでしたでしょうか。以下にご紹介した心得8か条をまとめました!

1. タスク依頼
・依頼するタスクはユーザーさんにとってどのようなインパクトがあるのかを伝えること

2. スケジュール調整〜制作 の心得
・自分の見積もり工数 + バッファをとった工数でスケジュールを立てること
・締め日を決めて、逆算して細かくスケジュールを切ること

3. フィードバックの心得
・まず、肯定すること
・なるべく文字化すること
・答えは言わず、考えてもらうようにすること

4. リリース・振り返り
・労いの言葉は必ずかけること
・見積もり工数と実工数との差分は必ず振り返ること

新人デザイナーさんとのコミュニケーションは、なるべく手厚めにフォローをする・気づきから成長してもらうための工夫を入れたりしています。タスクやスケジュール感によってはできる・できない・やらないことはあると思いますが、これらの"心得"を持っておくことによってデザインチームとして、お互いに気持ち良く制作ができると思います。

私はまだディレクションを任されて3ヶ月目ですが、冒頭でも書いたように本当に"自分でつくるよりも何倍もつくってもらうほうが難しい"ということを実感しました。
この記事をまとめている際に過去を振り返っていて、こうしてまとめている心得はすべて私がこれまで実際にディレクターさんや先輩エンジニアさんからしていただいて嬉しかったコミュニケーションを参考にしていることに気がつきました。私も、嬉しいと思っていただけるようなディレクションができるようになるのが目標です。

まだまだ完璧にこなすことは難しいですが、より良いコミュニケーションがより良いプロダクトをつくると思っているので、これからも頑張ります!