文字っぽいの。

文字を書いています。写真も混ざります。

「これバグじゃね?」で始めるコミュニケーションはやめよう。

バグを見つけて教えてくれるのは嬉しいしありがたい。ユーザの体験損失や脆弱性を防ぐことができて良い。これは何にも勝る絶対的な真理である。

しかし、なにか変な挙動を見つけた時に脊髄反射的に「これバグじゃね?」と言うのは良くない。この発言はただの いちユーザの発言 であり、サービスやアプリを提供する側の人間としては、恥ずべき発言だと思う。

そもそも、その挙動の「バグか、仕様か」を判断するのは開発者であって、ユーザではない。「これバグじゃね?」は思考停止した愚かな発言であり、

  • この文脈上は正しい
  • あるプラットフォームの制約や文化の上では正しい
  • 人月や負債の関係でこれが限界だった
  • メインのスコープじゃないし致命的じゃないから後回しにしてる

という背景がある(かもしれない)挙動を十把一絡げに「バグじゃね?」と言うのは良くない。

「これバグじゃね?」と言われた時の感覚は「なんかお前臭くね?」と言われたのと同じ感じがある。「えっ、マジで?なんか変なの食べたっけ?にんにく?ニンニク食べたっけ?昨日風呂入ったよな?入ったよ。入浴剤も入れて入ったね。もしかして加齢臭?これが噂の加齢臭なのか?もしかしてワキガ?ワキガなのか?手術とか受けたほうが良いのかな?つら。」ぐらいに脳みそが回転してバグに構える。それだけエンジニアはバグに対して敏感に生きている。

もし「バグじゃね?」と言われた挙動がバグだった場合は「バグだわ。死にたい。」という気持ちになるし、バグじゃなくて意図した挙動だった場合は「なんやお前殺すぞ。」という気持ちになる。上記の例では「あぁ、お前の匂いじゃないわ。なんかエアコンが臭いわ。お前臭くねーわwwがははww」とか言われた感じですね。殺してやりたくなりますよ。

じゃあどうすればいいの?

明らかなバグを見つけた時

アプリを触ってたらクラッシュしたり、ふぁぼったのに反映されてなかったり、500エラーが出てたり。明らかなバグなら「バグっぽいです。」と教えてあげればよいです。

また、それを伝える際に どういう手順で動かすとバグる を一緒に伝えてあげると大変助かると思います。「この画面でボタン押したらバグったけど、今は大丈夫。」って言われても「何もしてないのにパソコンが壊れた。」と言われるのと同じくらい「どうしろってんだ」感があります。

なんか変な挙動を見つけた時

「この画面で、こうしたらAになったんですが。なんか私的には、Bになる気がするんですが、なにか理由がありますか?」とか聞いてもらえると、意匠がある場合はそれを教えることができますし、ただのバグなら「殺してくれ。」って良いながらIssueを立てます。

まとめ

最初から殴る気満々でコミュニケーションを始めるのはやめよう。

自転車パクられたけどチームメンバーにプレゼントしてもらった。

2015年10月、僕は自転車をパクられた。スーパーで買い物している時に、鍵をかけてなかったので窃盗犯にとってはとてもありがたい状態だったであろう。「鍵かけてないのが悪い」という意見もあると思うが、自転車をパクった奴が悪いのである。「痴漢されるのは扇情的な格好をしていた被害者も悪い」みたいな言説は本当にしょうもない。とにかく毎日スーパーに立ち寄るたびに犯人を呪っていたし、いい感じに車に轢き殺されてギリギリ死なない重症をキメて欲しいと今でも思ってる。

そんなわけで自転車がなくなり、毎日片道50分かけて徒歩で通勤することになった。案外50分歩くというのは簡単で、満員電車に押し込められておっさんの芳香に包まれるより全然良い。「自転車が無くなったくらいで遅刻などしない。窃盗犯には屈しない。」という謎の使命感を持って通勤していた。ただ、毎日2時間が移動によって消費されると結構不便である。可処分時間が減ると体調管理も甘くなるし、なにより趣味のコーディングやゲームをする時間が無くなる。料理をする時間ももったいないし、徒歩で帰宅中に腹が減ってしょうがないので、コンビニ飯や外食が増えた。

そんな僕を憂いて、誕生日プレゼントとして、チームメンバーが自転車をプレゼントしてくれた。圧倒的感謝。自転車はAmazonサンタがオフィスに届けてくれた。Amazonで自転車買えるんですね。すごい。

f:id:FromAtom:20160413192518j:plain

新しい自転車はデフォルトで鍵も変速機もライトもついているし、オレンジ色でかわいくて最高という感じ。ちなみにAmazonで買うと防犯登録はされてないので、自分で自転車屋に持って行って登録してもらう必要があるので注意。

チームメンバーのおかげで今日も元気に出社できました。ありがとうございます!問題は今日の天気予報が夕方から雨ってことです。

XcodeでiOS開発を始める前にしておくと便利な準備

デバイス接続時にPhoto.appを起動しないようにする

バグ検証時に検証機ではなく、個人のiPhoneを接続することがたまにありますが、便利なことにPhoto.appが起動して、他人の写真が見放題です。「あぁ!すいませんすいません!」と焦って⌘Qを連打する前に、そもそも起動しないように設定しておきましょう。

defaults -currentHost write com.apple.ImageCapture disableHotPlug -bool YES

元に戻したい場合は

defaults -currentHost write com.apple.ImageCapture disableHotPlug -bool NO

で元に戻ります。

インデント設定を変える

これは参加しているプロジェクトによりますが、 GitHubSwift Style Guideに追従する場合、インデントはHard Tabになります。

XcodeのPreferences -> Text EditingのIndentationタブで、下記画像のように設定しましょう。

f:id:FromAtom:20160223155319p:plain

行末のスペースを削除 & 空白のみの行から空白を削除

XcodeのPreferences -> Text EditingのEditingタブで、Automatically trim trailing whitespaceIncluding whitespace-only linesにチェックを入れます。

f:id:FromAtom:20160223155500p:plain

爆速でiOSアプリのカラー設定をするための`extension`と`enum`

アプリを爆速で作りたい時に、最も時間を浪費するのが色の指定です。StoryBoard上で設定してしまうと、あとから調整をしたい場合、複数ある画面全てを渡り歩いて、丁寧な手作業で色をポチポチしていく必要があります。また、UIColorを使う場合でも、設定があちこちに分散してしまったり、RGB[0 - 255]での設定が難しくてつらい気持ちになったりします。

なので、Webで一般的な16進数表記でUIColorを生成できるようにして、生成したい色のセットをenumで管理するようにしました。

色を指定する際は、16進数で書けたほうが便利なのですが、UIColorは16進数表記でイニシャライズさせてくれません。ので、拡張します。

// 16進数表記からUIColorに変換する拡張
extension UIColor {
    convenience init?(hexString: String, alpha: CGFloat = 1.0) {
        let validatedHexColorCode = hexString.stringByReplacingOccurrencesOfString("#", withString: "")
        let scanner = NSScanner(string: validatedHexColorCode)
        var colorCode: UInt32 = 0

        guard scanner.scanHexInt(&colorCode) else {
            print("ERROR: 色変換に失敗しました。")
            return nil
        }

        let R = CGFloat((colorCode & 0xFF0000) >> 16) / 255.0
        let G = CGFloat((colorCode & 0x00FF00) >> 8) / 255.0
        let B = CGFloat(colorCode & 0x0000FF) / 255.0
        self.init(red: R, green: G, blue: B, alpha: alpha)
    }
}

これで UIColor(hexString: "#ffffff")インスタンスを生成することが出来ます。ちなみに、ここの処理は最初は関数になっていたのですが、最強のアルバイト氏が書きなおしてくれました。convenienceってこうやって使うんかって知った。さすが最強。

次にいくつかの16進数カラーコードを、enumで管理します。

// 色設定
enum ColorSet: String {
    case Background   = "F9F5EF"
    case Primary      = "2E97D8"
    case White        = "FFFFFF"
    case Gray         = "D0CAC1"

    var UIColor: UIKit.UIColor {
        return UIKit.UIColor(hexString: self.rawValue)!
    }

    var CGColor: UIKit.CGColor {
        return self.UIColor.CGColor
    }
}

こんな感じで定義しておけばColorSet.Primary.UIColorと呼び出すことができて大変便利です。また、急に「寒色系じゃなくて暖色系の色合いがいい」と言われた場合でも、このColorSetをいじるだけでアプリ全体の色を調整する事が可能になっています。またこれにより、Web側やSketch等各種デザインツールで設定されたカラーコードを、簡単に反映する事ができるようになりました。

Swiftの"[weak self]"にアクセスする時に"if let weakSelf = self"とか"self?"を書きたくない人へ

今まで

大体の場合、

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { [weak self] response in
    guard let weakSelf = self else {
        return
    }
        
        // do something...

    weakSelf.tableView.reloadData()
}

とか

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { [weak self] response in
        // do something...

    self?.tableView.reloadData()
}

と書きます。

違う書き方

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"]).responseJSON { [weak self] response in
    guard let `self` = self else {
        return
    }

        // do something...

    self.tableView.reloadData()
}

便利!

余談

SlackのSwiftJPチャンネルで色々議論されてて面白い。個人的には、// do something...の部分が複雑じゃない場合は便利だと思ってる感じです。

追記