見出し画像

イケてるフリーランスエンジニアが残していったコードの事例シリーズ - 1


はじめに

※ このnoteに記載されている事例はフィクションの場合もあります

これまでiOSエンジニアとして企業で働いた時に、フリーランスエンジニアの方々と一緒に働くことがありました。

彼らのほとんどが個人開発で売上が何千万円もあったりAppStoreランキングの上位にいたり素晴らしい商才と行動力と実行力の持ち主で、いわゆるイケてるフリーランスエンジニアという方々でした。
そしてどこかで社長と意気投合して、いつの間にか引っ張ってきたみたいなことが多かったように思います。

ただ、彼らの多くが正社員として雇われて安月給で働くより、自分の才能を信じてひとりでやっていった方が良いという方々でしたので、あくまでプログラミングは売上を出す手段なので、誰かにプログラミングを教わることもなく、チームで意思疎通のしやすいソースコードや効率的に修正しやすいコードのノウハウを知ってるわけではありませんでした。

ここではそんなイケてるフリーランスエンジニアの方々が残していったソースコードの一例を紹介していきます。

イケてるメソッド

女子トイレを利用していいかどうか判断するメソッドがあるとします。

func canUseWomenToilet(isFemale: Bool, age: Int, withParent: Bool) -> Bool {
    // 女性であれば利用できる
    if isFemale { return true }
    // 年齢が10歳以下で親が同伴なら利用できる
    if age <= 10 && withParent { return true }
    // それ以外は利用できない
    return false
}

ただし、すでにこれはプロジェクト全体であちこちで使われています。

// プロジェクト内でこういう処理が100箇所ぐらいある
if canUseWomenToilet(isFemale: false, age: 20, withParent: false) {
    
}

イケてる仕様変更

ここで、仕様変更で都内であれば「心が女性の男性は女子トイレを利用できる」となったとします。

イケてる修正

イケてるフリーランスエンジニアはこう書き足しました。

func canUseWomenToilet(isFemale: Bool, age: Int, withParent: Bool) -> Bool {
    // 女性であれば利用できる
    if isFemale { return true }
    // 男性でも年齢が10歳以下で親が同伴なら利用できる
    if age <= 10 && withParent { return true }
    // それ以外は利用できない
    return false
}


// 都内の場合はこちらのメソッドを呼ぶ
func canUseWomenToilet(isFemale: Bool, age: Int, withParent: Bool, hasFemaleIdentity: Bool) -> Bool {
    // 女性であれば利用できる
    if isFemale { return true }
    // 男性でも心が女性であれば利用できる
    if hasFemaleIdentity { return true }
    // 年齢が10歳以下で親が同伴なら利用できる
    if age <= 10 && withParent { return true }
    // それ以外は利用できない
    return false
}

利用箇所はこのような感じです。

// プロジェクト内でこういう処理が100箇所ぐらいある
if canUseWomenToilet(isFemale: true, age: 20, withParent: false) {
    
}

// 今回追加した処理
if canUseWomenToilet(isFemale: false, age: 30, withParent: false, hasFemaleIdentity: true) {
    
}

確かにこれで新しい要件が必要な箇所は新しいメソッドを呼べば仕様通りに動きます。

イケてる修正の問題点

ただし、今後canUseWomenToiletメソッドを呼ぶ箇所が増えてきた時にはどちらのメソッドを呼べばいいのでしょうか?
新しい仕様追加がある度に同じようなメソッドを増やすのでしょうか?

もしそれで同じようなcanUseWomenToiletメソッドが10個以上になった後で根本的に仕様変更や途中でログの出力を挟みたいとなったら全部書き直す必要が出てきます。

イケてる疑問点

ではなぜイケてるフリーランスの方は元のメソッドを次のように書き換えなかったのでしょうか?

func canUseWomenToilet(isFemale: Bool, age: Int, withParent: Bool, hasFemaleIdentity: Bool) -> Bool {
    // 女性であれば利用できる
    if isFemale { return true }
    // 男性でも心が女性であれば利用できる
    if hasFemaleIdentity { return true }
    // 男性でも年齢が10歳以下で親が同伴なら利用できる
    if age <= 10 && withParent { return true }
    // それ以外は変態なので利用できない
    return false
}

イケてるフリーランスの方が言うには
「すでに100箇所以上で使われているので呼び出し側を全部以下のよう書き換えないといけない。書き換える以上全部動作テストをやり直さないといけない。だから大変である」
というわけです。

// プロジェクト内でこういう処理が100箇所ぐらいある
// コレらにhasFemaleIdentity: falseを書き足す必要がある
if canUseWomenToilet(isFemale: false, age: 20, withParent: false, hasFemaleIdentity: false) {
    
}

イケてる原因

つまり今回の原因は、イケてるフリーランスの方はデフォルト引数を知らなかったわけです。

堅実な対応

このように既存のメソッドにパラメータを追加したいが、すでに使われてる箇所に影響のないようにしたい場合はこのようにします。

// hasFemaleIdentityを足すがデフォルトでfalseとし既存の実装と動きが変わらないようにする
func canUseWomenToilet(isFemale: Bool, age: Int, withParent: Bool, hasFemaleIdentity: Bool = false) -> Bool {
    // 女性であれば利用できる
    if isFemale { return true }
    // 男性でも心が女性であれば利用できる
    if hasFemaleIdentity { return true }
    // 男性でも年齢が10歳以下で親が同伴なら利用できる
    if age <= 10 && withParent { return true }
    // それ以外は利用できない
    return false
}

利用側はこのようになります。

// プロジェクト内でこういう処理が100箇所ぐらいある
// hasFemaleIdentityはデフォルトでfalseだから書き換える必要がない
if canUseWomenToilet(isFemale: false, age: 20, withParent: false) {
    
}

// 新しく利用する箇所だけhasFemaleIdentityをtrueにする
if canUseWomenToilet(isFemale: false, age: 20, withParent: false, hasFemaleIdentity: true) {
    
}

これだと無駄に同じようなメソッドが増えることなく、既存の実装に影響を与えることなく、仕様追加ができるようになります。

おわりに

他にもまだまだイケてる実装にたくさん出会ったのでいずれ紹介していきたいと思います。

この記事が気に入ったらサポートをしてみませんか?