しおメモ

雑多な技術系ブログです。

Swiftのメソッドごとのコンパイル時間を表示するワンライナー

忙しい人向けに、.xcactivitylogからメソッドのコンパイル時間を抽出するワンライナーです。

gunzip -c -S .xcactivitylog hoge.xcactivitylog | perl -pe "s/\r/\n/g" | grep -E "^\d+\.\d+ms" | sort -nr | uniq | head -100

中身はただのgzipですが、\rが厄介なのでperlで処理しています。

% gunzip -c -S .xcactivitylog *.xcactivitylog | perl -pe "s/\r/\n/g" | grep -E "^\d+\.\d+ms" | sort -nr | uniq | head -100

227.21ms        .../Presentation/View/ToastView.swift:64:10 instance method showWithAnimation()
200.22ms        .../Utility/DependencyAssembly.swift:12:22  class method setup()
192.17ms        .../Presentation/ViewModel/Implementation/ColorSelectorViewModel.swift:75:10        instance method makeFlowLayout(with:)
...

もっと忙しい人向け

現在のディレクトリから最新のログを拾ってきます。便利〜♨

gunzip -c -S .xcactivitylog $(ls -lt | grep -E "\.xcactivitylog$" | head -1 | awk '{print $10}') | perl -pe "s/\r/\n/g" | grep -E "^\d+\.\d+ms" | sort -nr | uniq | head -100

NimbleのPredicateの自作方法とサンプル

Nimbleでテストを書いていた際に、共通部分をPredicateとして自作してまとめたいことがあったので、実装の方法と簡単なサンプルを記しておきます。

実装方法

github.com

Quick/NimbleのMatchersの中で、beEmptybeNilを見るとわかりやすいです。

matcherで使うために、Predicateを返すメソッドを定義する必要があります。
PredicatePredicate.simplePredicate.simpleNilableを使うと簡単に、生成することが出来ます。

func hoge<T>() -> Predicate<T> {
    return Predicate.simple("hoge") {
        // 判定処理
    }
}

PredicateStatusmatchesdoesNotMatchfailの3つからなるenumです。

説明
matches 判定条件に合致
doesNotMatch 判定条件に合致しない
fail 入力が上の2つのいずれの状態にもなりえない

.failは特殊ですが、ドキュメントコメントにあるように、nilexpectに入ったときなどに起こります。
expect(nil).to(equal(1))expect(nil).toNot(equal(1))はどちらもマッチ扱いにならずfailとなります。

サンプル

その1: ダウンキャストして比較

func beA<T, U: Equatable>(_ object: U) -> Predicate<T> {
    return Predicate.simple("be a") { actual in
        guard let actual = try actual.evaluate() as? U else { return .fail }

        return PredicateStatus(bool: actual == object)
    }
}

名前はCoreMatchersから拝借しました。

ダウンキャストに失敗した場合は.failとして、成功した場合は比較を行います。
条件式に対しては、PredicateStatus(bool: Bool)を使うことで簡単にPredicateStatusを作ることが出来ます。

その2: enumのassociated valueを比較

enum HogeCases {
    case hoge(count: Int)
    case fuga
}

func beHogeCountIs(_ expected: Int) -> Predicate<HogeCases> {
    return Predicate.simple("be hoge count is") { actual in
        guard let actual = try actual.evaluate() else { return .fail }
        guard case let .hoge(count) = actual else { return .doesNotMatch }

        return PredicateStatus(bool: count == expected)
    }
}

// 利用例
expect(HogeCases.hoge(count: 1)).to(beHogeCountIs(1))

enumのassociated valueを見る時のPredicateです。
.hogeでなかった場合は、toNotにしたときに引っかかってほしいため、doesNotMatchを返します。

実際のケースでもっと複雑な比較になっても、一度Predicateを作っておけば、複数のテストケースで利用でき、見通しが良くなります。

転職活動のお話

転職してから1ヶ月たったので、書いてみます。
サイト名は出さないつもりなので、書いても何ももらえないやつです😣

なぜ転職したか

いろいろ理由はありましたが、一言で言うと当時の環境に何も魅力を感じられませんでした。

👇See also: ランボー怒りの退職エントリ

scior.hatenablog.com

異動もできないとのことだったので、転職するに至りました。

どう転職したか

1月頃、某指名方式の転職サイトの広告が目に止まったので、そちらに登録しました。

当時は業務が忙しく、時間が取れなかったため、レジュメを書いて、こちらから待つ方式のほうが負担が少ないという判断で、そのサイト1本に絞りました。
とくに、iOSやサーバーサイドという指定はしませんでしたが、次はどれか一つに集中したいという気持ちはありました。

2月中にありがたいことに、10社ほど指名をもらうことができましたが、その後も多忙が続いたため、残念ながらすべての会社に伺う事は出来ませんでした。
選んだ基準として、フルスタック的な働き方を求めるところが多かったため、なんとなく尚早かと思い、それらの指名は辞退しました。

結果として、3月に内定をもらった会社に入社することとなりました。

よかったこと

レジュメを書いていく中で、自分が何をしたいか、今までの経験がどう今後に活かせるかを考えるきっかけになりました。

他の企業を訪ねて、自分の知らない色々な文化や技術があることを知れたのも良かったです。
きれいなオフィスを見るのも楽しかったです。

反省点

反省点は2つあります。

一つは、とにかく時間が足りなかったことです。
その時の業務が大変だったので、面談も仕事が終わってからしていたため、下調べをする時間や履歴書を書く時間を確保するのが大変でした。
初めてなので、勝手がわからなかったのですが、もう少し腰を据えてやっても良かった気がします。

もう一つは、アウトプットを示せなかったことです。
転職するにあたり、やはりエンジニアなので、何かしらアウトプットが無いと説得力がないと感じられました。
自らの意思ではないとはいえ、それまでの業務内容がかなりとっ散らかっていたため、ためらってしまったのですが、ブログを貼るくらいはしても良かったと反省しています。(本当に何も見せなかった)

これから

今度の環境では、仕事の中でやりたいことができればいいかなと考えています。
当面はiOS中心で頑張っていきます。

また、空き時間で何かサブの活動をやりたいと考えていますが、何をやるかはもう少し考えてみたいです。コーディングではないかも知れません。

なんかまじめな内容になってしまった...😎