リバース・エンジニアリング

Flultterとテックブログと時々iOS

Swiftでのプロトコル指向のプログラミングを考えてみる

概要

Swiftのプロトコル指向プログラミングのベストプラクティスがわからなかったので、海外で販売されている本を読みながらXcodeのplaygroundで挙動を見ながら勉強していきました。

これはその備忘録です。

Introducing protocol extensions (protocol extensionの導入について)

アプリ開発でよく見るプロトコル拡張の使い方はUIColorStringといった既存の型に新しいメソッドを追加するやり方ではないでしょうか。

ProtocolPlayground.swift
extension String {
    func shout(){
        print(uppercased())
    }
}
"Protocol extension is pretty cool".shout() // PROTOCOL EXTENSION IS PRETTY COOL といった感じに大文字に変換される

こんな感じですね。

それに対して下のコードはプロトコルに新しいインターフェースを定義してそれをextensionで実装していく流れになります。

ProtocolPlayground.swift
protocol TeamRecord {
    var wins: Int { get }  // 勝ち数
    var losses: Int { get } // 負け数
    var winningPercentage: Double { get } // 勝率
}

extension TeamRecord {
    var gamesPlayed: Int { // 試合数
        return wins + losses
    }
}

struct BaseballRecord: TeamRecord {
    var wins: Int
    var losses: Int
    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses)
    }
}

let bayStars = BaseballRecord(wins: 10, losses: 5)
print(bayStars.gamesPlayed) // 15 回
print(bayStars.winningPercentage) // 0.666666 ~

Default Implementations (デフォルト実装)

ProtocolPlayground.swift
// Before extensionで拡張前

struct BasketBallRecord: TeamRecord {
    var wins: Int
    var losses: Int
    let seasonLength = 82  // デフォルト実装が持てる

    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses)
    }
}

extensionで拡張させることで

ProtocolPlayground.swift
extension TeamRecord {
    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses)
    }
}

// After extensionで拡張後

struct BasketBallRecord: TeamRecord {
    var wins: Int
    var losses: Int
    let seasonLength = 82 // シーズンの長さ
}

let minneapolisFunctors = BasketBallRecord(wins: 60, losses: 22)
print(minneapolisFunctors.winningPercentage) // winningPercentage が使えるようになる // 0.7317

structの中の実装は少なくなるよね、といった話し。
さらにstructインスタンスはprotocol extensionで実装したものが使えるようになっています。

ProtocolPlayground.swift
struct HockeyRecord: TeamRecord {
    var wins: Int
    var losses: Int
    var ties: Int // 引き分けのプロパティ、 追加

    // Hockey のレコードは引き分けのプロパティを導入したので「勝率」の計算方法が変わる
    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses + ties)
    }
}

let chicagoOptionals = BasketBallRecord(wins: 10, losses: 6)
let phoenixStridables = HockeyRecord(wins: 8, losses: 7, ties: 1)

print(chicagoOptionals.winningPercentage) // 10 / (10 + 6) = 0.625
print(phoenixStridables.winningPercentage) // 8 / (8 + 7 + 1) = 0.5

Understanding protocol extension dispatching

ProtocolPlayground.swift
protocol WinLoss {
    var wins: Int { get }
    var losses: Int { get }
}

extension WinLoss {
    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses)
    }
}

struct CricketRecord: WinLoss {
    var wins: Int
    var losses: Int
    var draws: Int

    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses + draws)
    }
}

let miamiTuples = CricketRecord(wins: 8, losses: 7, draws: 1)
let winLoss: WinLoss = miamiTuples

print(miamiTuples.winningPercentage) // 0.5
print(winLoss.winningPercentage) // 0.53 drawsがカウントされないため

WinLossには引き分けの draws が存在しないので、winLossはprotocol-extensionの方のメソッドwinningPercentageを出力する

Type constraints

ProtocolPlayground.swift
// 概念
protocol PostSeasonEligible {
    var minimumWinsForPlayoffs: Int { get }
}

// PostSeasonEligible と TeamRecord に準拠している時だけ適用される
extension TeamRecord where Self: PostSeasonEligible {
    var isPlayoffEligible: Bool {
        return wins > minimumWinsForPlayoffs
    }
}
ProtocolPlayground.swift
// 具体例
protocol Tieable {
    var ties: Int { get }
}

extension TeamRecord where Self : Tieable {
    var winningPercentage: Double {
        return Double(wins) / Double(wins + losses + ties)
    }
}

struct RugbyRecord: TeamRecord, Tieable {
    var wins: Int
    var losses: Int
    var ties: Int
}

//struct HockeyRecord: TeamRecord {
//    var wins: Int
//    var losses: Int
//    var ties: Int
//
//    var winningPercentage: Double {
//        return Double(wins) / Double(wins + losses + ties)
//    }
//}

let rugbyRecord = RugbyRecord(wins: 8, losses: 7, ties: 1)
print(rugbyRecord.winningPercentage) // 0.5

Protocol-oriented benefits (プロトコル指向のメリット)

プロトコル指向のプログラミングをやるメリットとして

  1. Programming to interfaces, not implementations
  2. Traits, mixins and multiple inheritance
  3. Simplicity

のメリットを享受出来る。

Programming to interfaces, not implementations

プロトコルは実装にフォーカスするのではなくインターフェースにフォーカスする
protocol にinterfaceを持たせるのでprotocolを見ればどういった機能なのかわかるので最終的にはFatClassが無くなりそうだよね。

Traits, mixins and multiple inheritance

多重継承 の問題を解決する
interfaceをprotocolに持たせてextensionで実装を行い、それをstruct やclass に準拠させるのでクラスの共通実装が必要なくなる。そのため、BaseClassといった共通クラスを継承したサブクラスにする必要がないので A is B 問題を解決する糸口になる。

Simplicity

単純かつ、簡潔、簡易なものにする

あとがき

海外のプログラミング本は最初はクオリティとか本当に理解できるのかと疑ってましたが、日本で販売されているプログラミング本よりも大変わかりやすかったです。最初は英語の苦手意識がありました。ですが、それを乗り越えると英語の解説書の方が回りくどい表現がない分理解が早くなることがわかる。

delegateとかprotocolなどの専門用語を日本語に翻訳する方が難しい気もします。

英語と聞くとアレルギーを起こすエンジニアさんも多数いるとは思いますが、

海外の本は日本の受験英語みたいに難しい英文はそこまでないように思います。

だったら最初から英語の本を読みながら英語でプログラミングを理解する方がいい気がします。

ですが、これは個々人の好みの問題ではあるところだと思います。

SublimeTextからVisual Stuidio Codeに乗り換えしました

VSCodeに完全移行

Visual Studio Code

エントリのタイトル通りに今まで仕事でもプライベートでもメモがわりに使うテキストエディタをSublimeTextからVSCodeに完全乗り換えしました。確かSublimeTextは2014年ぐらいからずっと使っていたテキストエディタ。まだ現役で使うこともできるのですが、仕事の人たち、特に若手の方がVSCodeを使っていたのでこれはもう時代なんだなと思いました。私が2014年から SublimeTextを使っていた動機も同じその時の同僚が使っていたテキストエディタがそれだったからです。

VSCodeのいいところ

SublimeTextからVSCodeに乗り換えて一番感激したのがMarkdownに対応しているということ。
記憶に覚えてはいないが今はVSCodeで編集したMarkdownを右側のプレビューで見え方を確認しながらリアルタイムで編集しています。このリアルタイム感が良いです。私は性格的に文字入力をするのが大変億劫らしくてブログを更新するのが大変苦手であったが、VSCodeにしてからは見え方をリアルタイムで確認できるので文字入力のスピードが格段に上がりました。

ブログに記事を更新してから、あーこの行間で改行するのは読みにくかったんだなといつも後悔します。それがリアルタイムで見え方を確認するのでブログに記事を投稿してからの気持ちの差異が少ないので最近ではブログに投稿した後の確認をしていないぐらいです。あと、MarkdownなしだとHTMLのタグ打ちをしなければならないのですが、\

\

とタグ打ちするのが大変に好きでないことを知っているのでできれば文章を書いている最中はタグ打ちを気にしたくないんですよ。なので、私は基本Markdownで文章を編集しています。

使っているMarkdown

ちなみに私が普段使っているMarkdown

# (h1)
## (h2)
### (h3)

[リンク](url) (リンク)

`文字` (文字装飾)

```code```

これらを頻繁に使っています。

それとVSCodeが相性が良いのでとうとうVSCodeに完全移行することにしました。
最初はVSCodeの使い方が全く分からなかったのですが、使っていけば慣れるものですね。
これで文字数カウントみたいなものがあれば完璧ですね。プラグインを導入すればトータル文字数を見れるらしいとのことですがググるのがそんな得意ではないのでまた近い内かな。
あと、タブ機能も付いているから普段XcodeAndroid Studioでコードを編集する感覚に近いのも比較的大きいかもしれない。

もう時代はVSCodeなんだろうな。

注記

文字数カウントぽいプラグイン見つかりました。

(CharacterCount)https://marketplace.visualstudio.com/items?itemName=8amjp.charactercount

このプラグインをインストールして有効にすれば、ウィンドーの一番下のブルーの左側に xx Charactersといった感じで表示されてました。これでブロガーさんにとっては今何文字を入力したのかリアルタイムで意識しながら文章が書けますね。
これでまたライティング効率が上がります。

9月の総決算について書いてみる

9月の総決算

7月からブロックチェーンの勉強を本格的に始めましたのでDapps開発の経験が3ヶ月を越えました。9月末までの目標はとにかくDappsをブラウザで使えるレベルまで持っていけるようにすることでしたがなんとか達成できました。そこに至るまで新しい言語Solidityを覚えたりブラウザ連携をしなければ話にならないのでHTMLだったりCSSだったりと色々な言語を覚えました。6月を基準とするとこの3ヶ月間でのパワーアップ感は半端ないと思いました。

よく仕事しながら続けられたと自分でも感心してしまいます。
その分、プライベートの時間が少なくなりましたので10月はちょっとゆっくり過ごしたいですが、この月は自分で経営してる会社の決算日なので決算手続きに追われます。8~9月がオフィス移転・引っ越しだっただけに怒涛の4ヵ月となりそうです。

本業の方はAndroid開発が一旦落ち着きましたのでiOS開発に戻ろうか的な雰囲気があります。今回のAndroid開発でJava言語を覚えられたのは人生の中でも凄く大きいかな。

3ヵ月間で達成したこと

この3ヵ月間で自分でも達成、あるいは成長したことを上げるとするなら

  • Solidityの基礎がわかった
  • ブロックチェーンの将来の可能性が見えてきた
  • Web開発言語であるHTML, CSS, PHPの復讐ができた
  • PHPのLaravelを触れるようになった
  • Qiitaの投稿を増やした。コントリビュートが100を越えた

と中々の成長ぶりです。

9月に重い腰を上げながらPHPを触り始めましたがこの行動が正解でした。
Web開発に関してはRailsとかJavaもいいですが、結局PHPで緩く書くのがビギナーにとって近道であることが分かりました。Rubyもいいのですが、Rubyをデプロイできる安いレンタルサーバーが少なすぎて選択肢から外してしまいました。Railsはいい言語なんですけど、手っ取り早く・安く・あるいは海外で!、と言うことを考えるとRailsを使うことが出来なくなりました。

次の4半期での目標について

そのため、PHPクローラー開発などで触りながら覚えて行ってます。こいつは割と適当な書き方でも動いてくれるんで非常に便利です。(Pythonでもいいんだけど安いレンタルサーバーが少ない・・・)
ひとまずいろんなページをスクレイピングして情報を集めるところからスタート。
この10月~12月で商用レベルのTwitterクライアントを開発してリリースまで持っていくのが直近3ヵ月の目標です。友達がTwitterで集客したいとの事だったので使いやすいTwitter関連サービスを開発中です。
その開発にLaravelを使用しています。Laravel楽しいわ。

エンジニアはプライペートの時間も犠牲にして勉強すべきかどうかについて

こんにちは、たまっぺです。

IT業界では(と言うより、ブログ業界では)、ウェブ系やモバイル系の会社で働くエンジニアは業務時間外にも技術のトレンドを追いかけたり勉強会に参加したりと「プライベート時間中に特に己を磨くために鍛錬すべき」かどうかのトピックが流れてきます。

axia.co.jp

www.yutorism.jp

ネットサーファーによっては「もう何十回議論してんねん」って言うような話しですが恐縮ですが私自身もよくわかっていないこのタイミングで文章として残して置きたいと思ってブログをせっせと書いています。

プライベートでもエンジニアが勉強すべきかどうか

まずエンジニアがプライベートにも勉強すべきかどうかの前に、エンジニアが業務時間外にも勉強していようが文系のサラリーマンやマネジメント層たちは業務時間外に女のネーチャンの尻を追っかけている事実が変わらないと言うことです。 また、事務職や営業のネーチャンは日頃の仕事に対するストレスの鬱憤を解放するためにアフターは居酒屋にいい男を探すために合コンに出かけたり、歳をとるにつれて衰えていく肌のメンテのためにエステサロンに足を出向けるのである。 真面目なエンジニアは勉強会に参加したり登壇者が前日か二日前に「面倒くせー」と思いながらささっと作った資料を元にして発表するLT(ライトニングトーク)を聞いて非常にありがたがっている間、サラリーマンの方は新しい出会いを求めて合コンに参加したはいいが目の前にいるちょいブスのネーチャンを見て「あー、今日もハズレだわ」と哀れます。女のネーチャン側はというとネーチャン側で「今日の合コン、全然冴えないおっさんばっかで完全にハズレだわ」と思いながらテーブルに置かれているハイボールをガバガバ飲んで時が過ぎるのも待つのだ。

そう言う両面の現実を見てしまうと「エンジニアってそんな頑張って技術を学んだり、トレンドを追っかける必要はないんじゃない」と思ってしまうのだ。

だから今回は業務時間外も勉強すべきかどうかは脇にとりあえず置いといて、業務時間外に勉強することのメリット・デメリットを私なりにまとめてみることにした。 だからあなたがすべきことはそのメリット・デメリットを考慮して自分に有利な方を選択すればいいだけだ。 そうすれば、あなたは有利な選択をしているのだからメリットしかないはずである。

業務時間外にも勉強するメリット

  • 最新の技術を学ぶことができる
  • 業務中に読書できない技術本を読むことができて業務中に変なコードを買いたり変な設計をして周りのメンバーに迷惑を書ける確率が減らせる
  • 周りのライバル(隣で働いているエンジニア)を出し抜いて自分が出征して面白い案件に携われる確率が上がる?
  • 勉強会に参加すればエンジニアの友達が増える
  • 友達が増えればそれはもう人脈だからそこから面白い話が飛んできて仕事が増える
  • もしかすると副業の発端となって年収が上がる
  • 新しい技術が自分に身につけば業務の内容をスマートにできる
  • 勉強し続けると臨界点が見えて勉強するコツを見つけると学びが楽しくなる
  • 頑張れば上のステージに進めるのである意味RPGをプレイしている感覚で楽しくなる時がくる

業務時間外にも勉強するデメリット

  • プライベート(遊ぶ)の時間がなくなる
  • 結果として自分のストレスが溜まって寝不足になる確率が上がる
  • 新しい出会いができる確率が下がる
  • 仕事の後にさらに負荷のかかる作業が入ることになる
  • 下手したらライトニングトークの登壇者になる確率が上がるので緊張する機会が増える
  • 周りがほぼ男性のライフスタイルになってしまう。
  • 寝不足になる恐れが増える。
  • ウェブ・モバイルに関わらずフロントエンドの技術のライフスタイルはかなり短いので学んだ技術が枯れやすいのでトレンドを追い続けなければならない
  • 20代での勉強は楽しいがそれを30代でも持ち越すと一気に重くなる
  • 勉強が趣味になる
  • なんか俺充実してない感が半端ない

余談

日本しか知らないのですが、日本のエンジニアの年収って400 ~ 800万円が期待するレンジですので業務時間外に勉強するメリットを享受できるのは800万円がMAXでそれ以上は上がりにくいので800万円を越えるとメリットが極端に下がります。 (もちろん、800万円からさらに上げる方法はあるとは思いますが) その時にもう一度「業務時間外にも勉強する価値があるかどうか」を考え直してはいかがでしょうか。

ただ、海外も含めたとしてもMAX2000万円が限界だと思うので限界幅は意外と狭いな。

iPhoneの新型機の登場

iPhoneの新型機について

今日、例のごとくAppleのiOS12のリリース日だったのでそれと同時に新型iPhoneの発売が確定しました。 今回の発表でAppleiPhoneのデザインが完全にあっちの方向に行くと言う未来が見えた。 それだけで十分な発表だった。

そりゃあiOSの開発言語のSwiftの作者が逃げたり、 共同創業者のウォズが逃げたりするわ。 だって発表中革新的なことがなかったし新型iPhoneを手に入れてまずやることがゲームって話なんだから。

どのiPhoneを購入すれば良いのか

今回のリリース内容をみて一発で今年は「iPhone8」が買いだと思いました。 私はM字のあのデザインは好きではないのです。 iPhoneXシリーズにはまだ手を出しません。

あのM字のデザインが好きな人ならシンプルにiPhoneXsじゃないでしょうか。

スペック重視ならiPhoneXRってやつじゃないでしょうか。