コードを書くにあたっての避けるべきことを紹介します。一般的によくないとされるアンチパターンだけでなく、私の経験上よくないと感じていることについても挙げています。

アンチパターンとは

アンチパターンとはソフトウェア開発において、問題を解決するために一般的に行われことではあるものの、結果的にそれが悲しい結果を引き起こすようなパターンのことを言います。

アンチパターンというものはプログラミング言語やライブラリ、フレームワークの数だけ存在するので、「なにかイケていないな?」と感じたらアンチパターンに嵌まり込んでいないかどうか、振り返ってみるのも大切なことです。

💡 イケてない = アンチパターンではありません

いくらイケてなくても、ほかにやりようのない泥臭い方法で実現しているだけのこともあります。これはむしろ、ほかの人がやりたがらない面倒な仕事を実現できていることになるので、競争力や訴求力に結びつきます。

eval()を使う

eval()は絶対に使わないでください!すべてを破壊されます。

このメソッドは引数として与えられた文字列をJavaScriptのコードとみなして実行します。つまり、動的にJavaScriptのコードを組み上げることで、任意のコードを実行できるようになるのです。どう?便利でしょう?

初心者プログラマがeval()の存在を知ると、あまりの便利さにこれを使った簡単な電卓やミニ言語をトランスパイルして実行できる環境を作りたくなる欲求にかられることがあります。

例えばですが、数式を入れるとその計算結果を返すボットを作りたくなったとしましょう。2 + 3のような簡単な式を計算させるのは、厄介ですができなくもなさそうです。2 + 3 * 4になると、掛け算が優先されるので、少し骨の折れる作業になりそうですが、まだなんとかなりそうです。括弧による計算順序の変更が入ってくる((2 + 3) * 4 + 5) * 6 あたりになると一筋縄ではいかなそうです。

そこでいいことを思いつくのです。eval()に計算させてしまえばいいのです。

eval('2 + 3 * 4')  // 14

素晴らしい!これでやりたいことは実現できました!なんでもeval()に放り込めばいいのです。さっそく仲間内で公開したところ、便利なものができたと喜んでくれました。しかし、数日後うんともすんとも言わなくなったと報告を受けました。それは次のようなコードを実行したからでした。

eval('while(true){}')

これは非常にまずい状況です。これっぽっちの簡単なコードでアプリケーションがハングしてしまいました。再起動して解消したものの、同じようなことが起きないようになにかしらの対策が必要のようです。

eval()は非常に強力で便利ですが、もし外から与えられる文字列が eval() に入力することがあれば、それは外から自由なコードを注入できることを意味しています。コードを実行すること自体が大きな危険を孕んでいますが、ほかにも内部で利用している変数の値を読み書きして、重要な情報を抜き取ったり、アプリケーションの挙動を書き換えることができたりするので、もう一度言いますが、絶対にeval()を使わないでください。

💬 入力できる文字列のパターンを制限すれば安全ですよね?

さて、どうでしょうね?🤔

コードクローン

ソフトウェア開発で起きる悲劇のひとつにコードクローンと呼ばれるものがあります。その名の通り、似たようなコードが頻出するというものです。生まれる理由は様々ですが、

  • 面倒くさがって、あるいは動作実績のあるコードをそのまま持ってきた
  • 複数人開発のコミュニケーション不足で各々が同じコードを書いた
  • 力量不足で処理の共通化ができず同じコードを放置した
  • 意図せず同じコードになってしまった

などが考えられます。

同じコードつまり同じロジックがあちこちに散らばっているということは、そのロジックを修正しなければなくなったときに、すべての出現箇所に対して同じ対応が必要になります。プロジェクトの規模小さいうちには十分対応可能ですが、大きくなるにつれて困難に、やがて不可能になっていきます。

たまたま同じ処理になってしまった、ということもあるので、すべてのコードクローンが悪というわけではありませんが、同じようなコードが出てきたらその処理を一般化できないかどうか、立ち止まって考えてみることも大事なことです。

すでに第3回 ドメインモデルでは注目すべき概念について説明をしているので、この連載の読者はコードクローンに対して感度が高くなっていることでしょう。

慣例に従わない

コーディング規則は言語により様々ですが、よほどのことがない限りは、その慣例に従うようにしましょう。細かいものまで挙げるとキリがないのですが、ふたつ大きいものを紹介するなら、識別子の書き方と括弧のスタイルになるでしょう。識別子の書き方にはいくつかあり、代表的なものには以下があります(JavaScriptにおける用途も記載してあります)。

  • UPPER_SNAKE_CASE: 定数
  • lower_snake_case: (使わない)
  • PascalCase: クラス名
  • lowerCamelCase: 変数名

括弧のスタイルはプロジェクトによっても変わりますが、一般的には次のようになります。

if (cond1) {
    // 条件1
} else if (cond2) {
    // 条件2
} else {
    // それ以外
}
 
const data = { name: 'John' }
 
function factorial(n) {
    if (n <= 1) {
        return 1
    }
    return n * factorial(n - 1)
}

しかし、一番大切なのはどんなスタイルであれど一貫性があることです。スタイルが混在するとコードを捉えにくくなり、混乱を招きます。慣れないうちはコードフォーマッタ等を活用することを検討してもいいでしょう。