35
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事誰得? 私しか得しないニッチな技術で記事投稿!

[ネタ記事]自分しかメンテできないコードの書き方 - プロジェクト破綻の一歩手前

Last updated at Posted at 2023-06-24

はじめに

みなさん、クソコード(失礼な言い方だな、個性だぞ個性)を書いた経験はありませんか?(私にはいっぱいあります)
ということで、今回は自分しかメンテできないコードの書き方を紹介しようと思います。
自分がいなくなったらプロジェクトが破綻するような、自分しかメンテできない(もしかしたら自分もメンテできない w)コードを書いて、自分の存在をアピールしましょう!

注意事項

  • これはネタ記事です。良い子はマネしないでね。
  • これはネタ記事です。良い子はマネしないでね。
  • これはネタ記事です。良い子はマネしないでね。
  • サンプルコードでは Python を使っています。

※基本的に Clean Code の反例をひたすらあげていますが、全てのベストプラクティス(の反例)を網羅しているわけではありません。また記事が長くなるので良い例はほぼ記述していません。気になる方はご自身で調べてみてください。

Repeat Your Self

メンテナンスの難易度の高いプログラムを書く際に、まずコードを冗長化させるのが基本です。何回も使う変数や処理はその都度書きましょう。例えば、商品総額を計算する処理があるとしましょう。

# 商品の数量と価格のリスト
# 商品の数量と価格のリスト
quantities = [5, 10, 3, 7, 2, ...]  # 商品の数量
prices = [100, 200, 150, 80, 120, ...]  # 商品の価格

# 商品ごとに総額と税金を計算する
total_prices = []
taxes = []

# 商品1の総額と税金を計算する
total_1 = quantities[0] * prices[0]
tax_1 = total_1 * 0.1
total_prices.append(total_1)
taxes.append(tax_1)

# 商品2の総額と税金を計算する
total_2 = quantities[1] * prices[1]
tax_2 = total_2 * 0.1
total_prices.append(total_2)
taxes.append(tax_2)

# 以下、商品3から商品100までの総額と税金を計算する処理を繰り返す...
# ...

# 商品100の総額と税金を計算する
total_100 = quantities[99] * prices[99]
tax_100 = total_100 * 0.1
total_prices.append(total_100)
taxes.append(tax_100)

# 総額と税金のリストを表示する
print("総額:", total_prices)
print("税金:", taxes)

この例では、quantities と prices に商品の数量と価格を保持し、ループ処理や関数切り出しを行わずに各商品の総額を個別に計算しています。また、税率も変数(定数)化するのではなく、毎回の処理時に書いてます。これにより、同じ処理を 100 回繰り返す冗長なコードになっているだけでなく、税率が変更されるたびの 100 箇所修正する必要が出てくるため、誰も触りたくなくなります。いい感じですね!

不必要なコメント&間違ったコメント

メンテナンスの難易度を上げるために、不必要なコメントをたくさん残せばいいのです。たまに実際の処理と全く違うコメントを書いて読む人を混乱させましょう。
例えば以下のように変数のコメントを書くことができます。

# 果物の集合です
pets = {"dog", "cat", "monkey"}

もう一例として、商品総額を計算する関数があるとしましょう。
一目でわかるような処理にもいちいちコメントを残しましょう。また、docstring に不要な情報や間違った挙動を示す内容を書いてみましょう。

def calculate_total_price(quantity, price_per_item):
    """
    これはcalculate_total_priceという関数である
    商品総額を税抜で返却する
    """

    # 数量と価格を掛け合わせて総額を計算する
    total = quantity * price_per_item

    # 税金を計算する
    tax = total * 0.1 # また上がるかも!

    # 総額に税金を加える
    total_with_tax = total + tax

    # 総額を返す
    return total_with_tax

いらない行を削除せずにどんどんコメントアウトしていくのもいいかもしれませんね。

def calculate_total_price(quantity, price_per_item):
    """
    これはcalculate_total_priceという関数である
    商品総額を税抜で返却する
    """

    # 数量と価格を掛け合わせて総額を計算する
    total = quantity * price_per_item

    # # 税金を計算する
    # tax = total * 0.1 # また上がるかも!

    # 税金を計算する
    tax = total * 0.15 # あがっちゃったw

    # 総額に税金を加える
    total_with_tax = total + tax

    # 総額を返す
    return total_with_tax

うん、いい感じ。
68747470733a2f2f7062732e7477696d672e636f6d2f6d656469612f465a79414b4844583041456279645f3f666f726d61743d6a7067266e616d653d6d656469756d.jpeg

スペースやインデントをランダムに入れる or 無視する

コードを読みにくくすることで、メンテナンスの難易度を上げることができます。構文エラーが発生しない限りスペースやインデントなどをランダムに入れたり、無視したりすると良いでしょう。

def add_numbers(a,b):sum=a+  b;return sum
result=add_numbers( 5,3) ;print("結果:",     result)

上記のコードを実行してみてください。エラーなんか出ませんよ。

間違った命名&意味のない命名

変数名や関数名を間違った名前や全く意味のない名前にすることで、コードを読む人を困惑させることができます。

liquid = "cat"

そう、猫は液体です。

もう一例見てみましょう。

def calc(a, b):
    x = a + b
    y = x * 2
    z = y / 3
    return z

result = calc(10, 5)
print("結果:", result)

どうですか。なんの計算を行なっているかわかりますか?(私もわからん)

すげぇ長い命名

また、変数名や関数名をすげぇ長い名前にすることも可能です。

def calculate_total_price_based_on_quantity_and_unit_price_and_tax_rate(quantity_of_items_in_cart, unit_price_of_item_in_cart, applicable_tax_rate):
    total_price_of_items_in_cart = quantity_of_items_in_cart * unit_price_of_item_in_cart
    tax_amount = total_price_of_items_in_cart * applicable_tax_rate
    total_price_with_tax = total_price_of_items_in_cart + tax_amount
    return total_price_with_tax

number_of_items = 10
price_per_item = 5.99
tax_rate = 0.08

final_price = calculate_total_price_based_on_quantity_and_unit_price_and_tax_rate(number_of_items, price_per_item, tax_rate)
print("最終価格:", final_price)

どうですか。読みにくいだろ(どや)!

深いネスト

条件分岐やループを書く際に、ネストを増やすことで、コードのメンテナンスの難易度を上げることができます。例えば、商品の在庫管理の処理を行う関数があるとしましょう。この関数では、膨大な条件で if 文をネストさせています。

def check_stock(product_name, quantity):
    if product_name:
        if quantity:
            if product_name == "apple":
                if quantity <= 0:
                    if quantity == 0:
                        if quantity % 2 == 0:
                            if quantity % 5 == 0:
                                if quantity % 10 == 0:
                                    if quantity % 20 == 0:
                                        if quantity % 50 == 0:
                                            print("在庫切れです。")
                                        else:
                                            print("在庫があります。")
                                    else:
                                        print("在庫切れです。")
                                else:
                                    print("在庫があります。")
                            else:
                                print("在庫切れです。")
                        else:
                            print("在庫があります。")
                    else:
                        print("在庫切れです。")
                else:
                    print("在庫があります。")
            else:
                if product_name == "banana":
                    if quantity <= 0:
                        if quantity == 0:
                            if quantity % 2 == 0:
                                if quantity % 5 == 0:
                                    if quantity % 10 == 0:
                                        if quantity % 20 == 0:
                                            if quantity % 50 == 0:
                                                print("在庫切れです。")
                                            else:
                                                print("在庫があります。")
                                        else:
                                            print("在庫切れです。")
                                    else:
                                        print("在庫があります。")
                                else:
                                    print("在庫切れです。")
                            else:
                                print("在庫があります。")
                        else:
                            print("在庫切れです。")
                    else:
                        print("在庫があります。")
                else:
                    print("商品名が存在しません。")
        else:
            print("数量を入力してください。")
    else:
        print("商品名を入力してください。")

check_stock("apple", 7)

おお、いい形してるね w
この例では、商品の在庫を確認するための関数に複数の条件分岐がネストされています。これにより、コードの可読性が低くなり、メンテナンスの難易度が上がっています。

長いワンライナー

長いワンライナーも活用すると良いでしょう。

def calculate_total_price(products): return sum([p["price"] * p["quantity"] if p["quantity"] > 0 else 0 for p in products if p["price"] > 0 and p["quantity"] > 0])

この例では、商品総額を計算する関数をワンライナー書いています。さらにリストの内包表記や条件分岐も使われています。
長いから横スクロールしてね。

巨大な関数やクラス

関数などを書く際に、ある処理を別の関数に切り出して関数を小さくしようとしていませんか?メンテナンス性が向上する可能性があるからしなくていいです。
例えば、下記のような全体的な注文処理を行うための巨大な関数があるとしましょう。注文の各ステップや関連する処理が一つの関数内に組み込まれていて、関数の中に複数の責務が混在しています。

def process_order(order):
    # ユーザーの情報を取得
    user = get_user_info(order["user_id"])
    # 商品情報を取得
    products = get_products(order["product_ids"])

    # 送料の計算
    shipping_fee = calculate_shipping_fee(order["shipping_address"])

    # 支払い処理
    if order["payment_method"] == "credit_card":
        charge_credit_card(order["total_price"])
    elif order["payment_method"] == "paypal":
        process_paypal_payment(order["total_price"])

    # 在庫の更新
    for product in products:
        update_product_stock(product["id"], product["quantity"])

    # 注文のステータスを更新
    update_order_status(order["id"], "completed")

    # メールの送信
    send_order_confirmation_email(user, order)

    # 注文の詳細をログに記録
    log_order_details(order)

    # ギフトラッピングの処理
    if order["gift_wrapping"]:
        process_gift_wrapping(order)

    # ポイントの付与
    assign_reward_points(user, order["total_price"])

    # クーポンコードの使用
    if order["coupon_code"]:
        apply_coupon_code(order["coupon_code"])

    # 返品処理
    if order["return_requested"]:
        process_return(order)

    # ギフトカードの処理
    if order["gift_card"]:
        process_gift_card(order)

    # その他の処理...

読む気失せますね。そう思わせれば OK!

コピーアンドペーストの乱用

みなさん多分普段からすでにやってるから紹介しなくてもいいかな〜まぁ要するに Google や Stack Overflow などで調べたやつをそのままコピペするってやつですね。
いいですか、動くプログラムを作ることが大事です。動けばいいのです。
1l8phnxpkta81.jpg

おわりに

以上、自分しかメンテできないコードの書き方(Clean Code などの反例)のご紹介でした。このネタ記事では、冗談や皮肉を交えながら、実際のソフトウェア開発においてよく遭遇する保守性や可読性の低いコードの書き方の一部を取り上げさせていただきました。

実際のチーム開発においては、バグの修正や新機能の追加、チームメンバーの変更など、プロジェクトの長期的な成功には、保守性の高いコードが欠かせません。コードを書く際には、自分だけでなく、将来のメンテナンス担当者や他の開発者を思いやる心構えも重要かと思います。

この記事がご参考になれば(ならんわ w)幸いです。

35
19
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?