Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

Objective-C→Swiftでどう書き換えたらいいの?をまとめてみた

初めまして、iOSエンジニアのすーです!4月からTimers Inc.で働き始めました。
社内では最年少です。笑

現在Fammでは、新規開発を行いつつ、Objective-Cで書かれたコードを少しずつSwift化するのを行っています。
既に、新規でコードを書く時はSwiftで書くように心がけ、暇がある時に慎重にObjective-Cで書いたコードを書き換えています。

そんなときに、「Objective-Cでこう書いてあったのをSwiftで書く時どうしたらいいの?」っていうケースに幾つか遭遇し、それを社内wikiにまとめたら、
「これTech blogに投稿できるんじゃね?」ってなったので、改めて内容を整理しつつ、公開することにしました!
SwiftからObjective-Cに徐々に移行していくときに遭遇しそうな内容をピックアップしています。

まだまだ私達もObjective-CからSwiftに模索しながら移行しているので、もっと良いベストプラクティスがあるかもしれないですが、これからSwiftに書き換えていくぞ!っていう人たちの参考になればと思います!

続きを読む

テストに投資した時間が、チームにどのような利益をもたらすか?

はじめまして。2016年2月にTimes.incに入社しましたサーバーサイドエンジニアの山口です。 よろしくお願いいたします。

はじめに

今回は、「テストに投資した時間が、チームにどのような利益をもたらすか?」について弊社で採用しているPHPテスティングフレームワークCodeceptionで記述したサンプルコードを交えながら、ご紹介したいと思います。

続きを読む

LINE Bot始まりましたよ

TimersのiOSエンジニア村本です。

今回は、巷で話題のLINE Botについてピックアップしたいと思います。
4月7日に「BOT API Trial Account」が発表されて、すでにいろんなBotが誕生しているようです。

blogs.itmedia.co.jp

note.mu

そして僕もNodeでBotを作ってみました。そこで感じたBotの未来について考察していこうと思います。

ざっくりこんな感じ
  • LINE Botを作るのはとっても簡単
  • LINE Botを使いこなすのはとっても難しい
  • 何れにしてもChat UIは素晴らしい
続きを読む

Moshi を実際に利用する際に役立つかもしれない Tips

こんにちは。Timers で Android 版の Pairy と Famm を担当させていただいております、さわいと申します。今回は、軽量・シンプルな JSONPOJO ライブラリである Moshi についてポストさせて頂きます。実際に導入する際、こういう Tips が世の中にあればもっと気軽に導入できるかも…という内容を焦点に記述した構成となっておりますので、そもそも Moshi とはなんぞやという方は、GitHub のページを参照するか、検索してご自身で調べて下さい。

Moshi

https://github.com/square/moshi

調べたこと

  1. POJOの名前とJSONのフィールド名が異なる際の対応

  2. 謎の精度を持つタイムスタンプをどう扱うべきか

  3. 型が int か boolean かが不定なフィールドを、統一した boolean 型に変換したい時、どう扱うべきか

  4. JSON から POJO に変換する際、Moshi は JSON の型や値によって POJO にどのような値を代入するのか

  5. JSON から POJO に変換する際、POJO にフィールドが定義されていても、JSON にはフィールド・値が存在しない場合、Moshi は POJO にどのようなデフォルト値を代入するのか

調べなかったこと

  • Moshi の Wiki に書いてあること

  • サンプルコードを見ればわかること

Tips

1. POJOの名前とJSONのフィールド名が異なる際の対応

アノテーションがあるので、そこで名前を定義すればOK。

public class Hello {
    @Nullable
    @Json(name = "1")
    private final String one;

    @NonNull
    @Json(name = "nick_name")
    private final String nickName;
}

2. 謎の精度を持つタイムスタンプをどう扱うべきか

PHP

<?php
microtime(true);

でタイムスタンプを取ってそのまま返却するようなAPIだと、例えば1000000003.0002といった、なんとも言えない精度で返される。これは困るので、その対応。

NazoTimestamp.java

@Retention(RetentionPolicy.RUNTIME)
@JsonQualifier
public @interface NazoTimestamp {
}

NazoTimestampAdapter.java

public class NazoTimestampAdapter {

    @ToJson
    String toJson(@NazoTimestamp BigDecimal bigDecimal) {
        return bigDecimal.toPlainString();
    }

    @FromJson
    @NazoTimestamp
    BigDecimal fromJson(String json) {
        return new BigDecimal(json);
    }
}

あとはMoshiのBuilderにAdapterをかまして、POJO側では

public class Ore {
    
    @NonNull
    @NazoTimestamp
    private final BigDecimal timestamp;
}

とすればOK。

3. 型が int か boolean かが不定なフィールドを、統一した boolean 型に変換したい時、どう扱うべきか

基本的に2.と同様。 カスタムAdapterを作成する。

public class NazoBoolAdapter {

    @ToJson
    String toJson(@NazoBool boolean bool) {
        return String.valueOf(bool);
    }

    @FromJson
    @NazoBool
    boolean fromJson(JsonReader reader) throws JsonDataException {
        try {
            if (reader.peek().equals(JsonReader.Token.NUMBER)) {
                return reader.nextInt() == 1;
            } else if (reader.peek().equals(JsonReader.Token.BOOLEAN)) {
                return reader.nextBoolean();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }
}
@Retention(RetentionPolicy.RUNTIME)
@JsonQualifier
public @interface NazoBool {
}

あとは Moshi の Builder に Adapter をかまして、POJO 側では

public class Ore {

    @NazoBool
    private final boolean nazoBool;
}

のように使用すればOK。

4. JSON から POJO に変換する際、Moshi は JSON の値によって POJO にどのような値を代入するのか

JSONの値が、POJOで指定された型と異なる場合に関しても、Moshiがどのように変換してくれるかを検証。

整数系

  • 検証コード

POJO

public class Card {
   public [short | int | long] number;
}

JSON

{"number": <代入値>}
  • 検証結果
<代入値> 変換可/否 POJO の number に入る値
1234 OK 1234
null NG 変換エラーでクラッシュ
"1234" OK 1234
false NG 変換エラーでクラッシュ
{"key", "value"} NG 変換エラーでクラッシュ

小数系

  • 検証コード

POJO

public class Card {
   public [float | double] number;
}

JSON

"{"number": <代入値>}"
  • 検証結果
<代入値> 変換可/否 POJO の number に入る値
1234.11 OK 1234.11
null NG 変換エラーでクラッシュ
"1234.12" OK 1234.12
false NG 変換エラーでクラッシュ
{"key", "value"} NG 変換エラーでクラッシュ

[補足] JSON における数字型問題

Moshi では、int, long, double はNUMBERという概念で認識される模様(float は不明だが、double扱い?)。

https://github.com/square/moshi/blob/master/moshi/src/main/java/com/squareup/moshi/JsonReader.java#L1418

なので、

{"value": 1.2234322}

のように書いても、POJOで定義された型が適切であれば適切にパースしてくれる模様(この場合は float か double を指定するのが正解)。

[補足]:Javaの数字まわりのデータ型

整数系

データ型
short 16ビット整数 -32768~32767
int 32ビット整数 -2147483648~2147483647
long 64ビット整数 -9223372036854775808~9223372036854775807

小数系

データ型
float 32ビット単精度浮動小数点数
double 64ビット倍精度浮動小数点数

Android Java (JDK 7) には unsigned はありません。JDK 8 からです。

String

  • 検証コード

POJO

public class Card {
   public String name;
}

JSON

{"name": <代入値>}
  • 検証結果
<代入値> 変換可/否 POJO の name に入る値
null OK null(メソッドを呼び出すとクラッシュする)
"" OK 空文字列(メソッドを呼び出してもクラッシュしない)
0 OK "0"
1.234 OK "1.234"
false NG 変換エラーでクラッシュ

boolean

  • 検証コード

POJO

public class Card {
   public boolean isPremium;
}

JSON

{"isPremium": <代入値>}
  • 検証結果
<代入値> 変換可/否 POJO の isPremium に入る値
true OK true
false OK false
null NG 変換エラーでクラッシュ
"true" NG 変換エラーでクラッシュ
0 NG 変換エラーでクラッシュ
1.234 NG 変換エラーでクラッシュ
[] NG 変換エラーでクラッシュ
{} NG 変換エラーでクラッシュ

array, list

  • 検証コード

POJO

public class Card {
   public [String[] | List<String>] weakTypes;
}

JSON

{"weakTypes": <代入値>}
  • 検証結果
<代入値> 変換可/否 POJO の weakTypes に入る値
null List OK null(メソッドを呼び出すとクラッシュする)
null Array OK null(メソッドを呼び出すとクラッシュする)
[] List OK データを持たないListオブジェクト(メソッドを呼び出してもクラッシュしない)
[] Array OK データを持たないArrayオブジェクト(メソッドを呼び出してもクラッシュしない)
["water", "fire"] List OK get(0): water, get(1): fire
["water", "fire"] Array OK [0]: water, [1]: fire
{"water", "fire"} List NG 変換エラーでクラッシュ
{"water", "fire"} Array NG 変換エラーでクラッシュ

Object in Object

  • 検証コード

POJO

public class Card {
   public Frame frame;
   public static class Frame {
       String color;
       int size;
   }
}

JSON

{"frame": <代入値>}
  • 検証結果
<代入値> 変換可/否 POJO の frame に入る値
{} NG 変換エラーでクラッシュ
null OK null
{"color": "red", "size": 20} OK frame.color = "red", frame.size = 20

5. JSON から POJO に変換する際、POJO にフィールドが定義されていても、JSON にはフィールド・値が存在しない場合、Moshi はどのようなデフォルト値を代入するのか

こんなデフォルト値が入る。

データ型
String型(String[]も含む) null
List型 null
オブジェクト型({}←これで囲まれたもの) null
boolean型 false
short, int, long の整数系 0
float, double の小数系 0.0

終わりに

JavaJSONライブラリはいくつかありましたが、Moshiは新しいだけあって、思想や設計も洗練されており、さらに提供元があのSquare様と、使う側としてはとても嬉しい限り。 Retrofit2との相性もよく、これから長い付き合いになりそうです。


子育て家族アプリFamm、カップル専用アプリPairyを運営する Timers inc. では、現在エンジニアを積極採用中!急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP : http://timers-inc.com/engineerings

とあるPHPエンジニアのキーボード設定 --Mac編--

はじめに

キーの中には押しやすい配置と押しにくい配置があります。基本的にキー配列というのは英語の文章を効率よく入力するために考えられていて、それが必ずしもキーボードを扱う他の作業に適しているとは限りません。プログラミングもその一つ。プログラムでは普段の文章入力では使うことのないいくつかの記号があり、それが入力をほんの少し妨げています。

今回は、PHPを書く上で頻繁に押すキーを簡単に押せるようにして仕事を1%効率化しよう。という内容を書きます。

遅くなりましたがサーバーエンジニアの浦野です。よろしくお願いします。

使うもの

なぜ日本語配列なのか

エンジニアの中には「なぜ日本語配列なのか?」と感じる方が多いでしょう。理由はシンプルで、キーの数が英語配列よりも2つ多いから。配列が気に入らなければ自分で変えてしまえばいいのでキーの数は多いに越したことがない。という考え方です。

変更前、変更後

まず最初に変更前と変更後の配列を。

変更前
f:id:timers-tech:20160321220850p:plain

変更後

f:id:timers-tech:20160321220858p:plain

基本的には小指の遠いところにあるキーを親指周辺や普段の手の配置で押せるようにする。という考え方です。...では完成形が分かった上で、ここからはこれに至るまでのやり方を説明します。

Karabinerの設定方法には2種類あります

既存の設定を使わせてもらう

Karabinerには最初から用意されている設定項目があります。チェックボックスを入れるだけなのでとっても簡単。

自分でカスタマイズした設定を使う

Karabinerは最初から用意されている設定とは別に、自分でXmlファイルを書いて設定することができます。/Library/Application\ Support/配下に設定ファイルがあります。

$ cat ~/Library/Application\ Support/Karabiner/private.xml
<?xml version="1.0"?>
<root>
</root>

一般的な設定内容

Slack専用設定

今やどこの会社でも利用しているチャットツール、Slack. この操作性を少しだけ上げてみます。Slackって実はキー操作でチャンネルの移動ができるんですね。Optionを押しながらの上下キーで上下のチャンネルに移動、それに地味に便利なのがOption+Shift+下で未読のチャンネルへの移動です。

でも矢印キーなんて押したくないので変更します。Ctrl+Nで下のチャンネル、Ctrl+Pで上のチャンネル、Ctrl+Wで未読のチャンネルに飛ぶ設定がこちら。Vimmerなのですがカーソル移動はEmacsが好きなのでこうしています。

押すキー 入力される文字
Ctrl+P 上のチャンネルに移動
Ctrl+N 下のチャンネルに移動
Ctrl+W 未読のチャンネルに移動
<appdef>
	<appname>SLACK</appname>
	<equal>com.tinyspeck.slackmacgap</equal>
</appdef>
<item>
	<name>For Slack CTRL+N=move next channel, CTRL+P=move previous channel, CTRL+W=move unread channel</name>
	<identifier>private.app_slack_move_channel_with_ctrln_ctrlp</identifier>
	<only>SLACK</only>
	<autogen>__KeyToKey__ KeyCode::N, ModifierFlag::CONTROL_L, KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L</autogen>
	<autogen>__KeyToKey__ KeyCode::P, ModifierFlag::CONTROL_L, KeyCode::CURSOR_UP, ModifierFlag::OPTION_L</autogen>
	<autogen>__KeyToKey__ KeyCode::W, ModifierFlag::CONTROL_L, KeyCode::CURSOR_DOWN, ModifierFlag::OPTION_L, ModifierFlag::SHIFT_L</autogen>
</item>

SemicolonをEnterに

Enterって頻繁に押す割に若干遠くに配置されているんですよね... 思い切ってEnterには右手の小指を割り当てましょう。

しかし単純に変更してしまうとSemicolonが入力できなくなるので以下のように変更します。

押すキー 入力される文字
Semicolon Enter
Ctrl+Semicolon Semicolon
Shift+Semicolon Plus
<item>
	<name>Semicolon to Return plus</name>
	<appendix>(+ Control+Semicolon to Semicolon, + Shift+Semicolon to plus)</appendix>
	<identifier>remap.semicolon2return_controlsemicolon2semicolon_plus</identifier>
	<autogen>--KeyToKey-- KeyCode::SEMICOLON, VK_CONTROL, KeyCode::SEMICOLON</autogen>
	<autogen>--KeyToKey-- KeyCode::SEMICOLON, VK_SHIFT, KeyCode::SEMICOLON, VK_SHIFT</autogen>
	<autogen>--KeyToKey-- KeyCode::SEMICOLON, KeyCode::RETURN</autogen>
</item>

ちょっと変わったもの

CtrlをEscapeに

Vimmerにとって恩恵の大きい設定になります。左手の小指の一つ左のキーを、単体で押したらEscape, 何かと組み合わせて押したらCtrlになるようにします。設定方法は簡単。既に用意されているのでチェックボックスを入れるだけです。

押すキー 入力される文字
Ctrl Esc
Ctrl+何か Ctrl+何か
+ Change Control_L Key (Left Control)
  v Control_L to Control_L
    (When you type Control_L only, send Escape)

SpaceをShiftに

地味に押しにくい割に頻繁に押すキーであるShiftを入力しやすくします。これも設定方法は簡単。既に用意されているのでチェックボックスを入れるだけです。単体で押すとSpace, 何かと組み合わせて押したらShiftになります。

押すキー 入力される文字
Space Space
Space+何か Shift+何か
+ Change Space Key
  v Space to Shift_L
    (When you type Space only, send Space)

PHPじゃないとありえないもの

PHPじゃないと...と言いつつ、実際は Ctrl/Shift + 英数/かなは汎用的に使える4パターンになっています。PHPを使うならあの気持ち悪い矢印を設定してしまうといいのではないでしょうか。

私は | \ -> => の4つを割り当てています。OR記号、特殊文字のエスケープ、クラス、Array対策ですね。Pythonみたいに遠い記号を使わなくて済むならこの4つをもっと上手く使えるのに...

押すキー 入力される文字
Ctrl+英数 ->
Shift+英数 =>
Ctrl+かな
Sfhit+かな \
<item>
	<name>Control_L KANA to |</name>
	<identifier>controll_kana_to_pipe</identifier>
	<autogen>--KeyToKey-- KeyCode::JIS_KANA, VK_CONTROL, KeyCode::JIS_YEN, VK_SHIFT</autogen>
</item>
<item>
	<name>Control_L EISUU to -></name>
	<identifier>controll_eisuu_to_arrow</identifier>
	<autogen>--KeyToKey-- KeyCode::JIS_EISUU, VK_CONTROL, KeyCode::MINUS, KeyCode::DOT, VK_SHIFT</autogen>
</item>
<item>
	<name>Shift_L KANA to \</name>
	<identifier>shift_kana_to_backslash</identifier>
	<autogen>--KeyToKey-- KeyCode::JIS_KANA, VK_SHIFT, KeyCode::VK_JIS_BACKSLASH</autogen>
</item>
<item>
	<name>Shift_L EISUU to =></name>
	<identifier>controll_eisuu_to_arrow2</identifier>
	<autogen>--KeyToKey-- KeyCode::JIS_EISUU, VK_SHIFT, KeyCode::MINUS, VK_SHIFT, KeyCode::DOT, VK_SHIFT</autogen>
</item>

おわりに

いかがでしたか?こんなマニアックな設定をする人はほとんどいないと思いますが、Karabinerは色んな設定ができて面白いのでぜひ試してみてください:)

KarabinerはMac限定なので、次はWindows編やります。

    • -

子育て家族アプリ[Famm](http://famm.us)、カップル専用アプリ[Pairy](http://pairy.com/)を運営する [Timers inc.](http://timers-inc.com) では、現在エンジニアを積極採用中!急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP : http://timers-inc.com/engineerings

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる