window.pipedriveLeadboosterConfig={です。 ベース:'leadbooster-chat.pipedrive.com'、 companyId:11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2、 } ;(function () { var w = window もし (w.LeadBooster) {なら console.warn('LeadBooster already exists') } else { w.LeadBooster = { {. q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: 関数 (n) { { this.q.push({ t: 'o', n: n, h: h }) this.q.push({ t: 't', n: n }) }, } } })() 悪いコーディングプラクティスでプロジェクトを潰さないためには?- The Codest
The Codest
  • 会社概要
  • サービス
    • ソフトウェア開発
      • フロントエンド開発
      • バックエンド開発
    • Staff Augmentation
      • フロントエンド開発者
      • バックエンド開発者
      • データエンジニア
      • クラウドエンジニア
      • QAエンジニア
      • その他
    • アドバイザリー
      • 監査&コンサルティング
  • 産業
    • フィンテック&バンキング
    • E-commerce
    • アドテック
    • ヘルステック
    • 製造業
    • 物流
    • 自動車
    • アイオーティー
  • 価値
    • CEO
    • CTO
    • デリバリー・マネージャー
  • チーム
  • Case Studies
  • ノウハウ
    • ブログ
    • ミートアップ
    • ウェビナー
    • リソース
採用情報 連絡先
  • 会社概要
  • サービス
    • ソフトウェア開発
      • フロントエンド開発
      • バックエンド開発
    • Staff Augmentation
      • フロントエンド開発者
      • バックエンド開発者
      • データエンジニア
      • クラウドエンジニア
      • QAエンジニア
      • その他
    • アドバイザリー
      • 監査&コンサルティング
  • 価値
    • CEO
    • CTO
    • デリバリー・マネージャー
  • チーム
  • Case Studies
  • ノウハウ
    • ブログ
    • ミートアップ
    • ウェビナー
    • リソース
採用情報 連絡先
戻る矢印 戻る
2021-05-06
ソフトウェア開発

悪いコーディング・プラクティスでプロジェクトを潰さないためには?

The Codest

バルトシュ・スライシュ

Software Engineer

キャリアをスタートさせたばかりのプログラマーの多くは、変数、関数、ファイル、その他のコンポーネントの命名について、あまり重要でないと考えている。その結果、彼らのデザイン・ロジックはしばしば正しく、アルゴリズムは素早く実行され、望みの効果をもたらしますが、ほとんど読むことができません。この記事では、さまざまなコード要素に名前を付けるときに何を指針とすべきか、また、極端から極端にならないようにするにはどうすればよいかを簡単に説明しようと思います。

なぜネーミングの段階をおろそかにすると、プロジェクトの開発が長引く(場合によっては非常に長引く)のか?

仮に、あなたとあなたの チーム を引き継いでいる。 コード 他のプログラマーから。その プロジェクト しかし、そのひとつひとつの要素は、もっとうまく書けたはずだ。

アーキテクチャに関して言えば、コード継承の場合、ほとんどの場合、それを手に入れたプログラマから憎悪と怒りを買うことになる。ある時は死につつある(あるいは絶滅した)技術の使用によるものであり、ある時は開発当初のアプリケーションに対する間違った考え方によるものであり、またある時は単に担当プログラマーの知識不足によるものである。

いずれにせよ、プロジェクトの時間が経つにつれて、プログラマーがアーキテクチャやテクノロジーに対して怒り狂うような状況になることはあり得る。結局のところ、どのアプリケーションも、時間が経てば、いくつかの部分の書き換えや、特定の部分の変更が必要になる。しかし、プログラマーを白髪にする問題は、受け継いだコードを読んで理解することの難しさである。

特に極端なケースとして、変数に意味のないアルファベット1文字が付けられていたり、関数に突発的な創造性が沸き起こり、アプリケーションの他の部分と整合性が取れていなかったりすると、プログラマーは暴走してしまうかもしれません。このような場合、正しい命名で迅速かつ効率的に実行できるコード解析は、例えば関数の結果を生成するアルゴリズムの追加解析を必要とします。そしてそのような解析は、目立たないとはいえ、膨大な時間を浪費します。

アプリケーションのさまざまな部分に沿って新しい機能を実装することは、それを分析するという悪夢を経験することを意味する。しばらくすると、その意図が明確でないため、コードに戻って再び分析しなければならない。

こうして、私たちはアプリケーションを支配する無秩序の竜巻に吸い込まれ、開発に関わるすべての人をゆっくりと消耗させていく。プログラマーはプロジェクトを嫌いになり、プロジェクトマネージャーは開発期間が絶えず伸び始める理由を説明するのを嫌いになり、顧客は信頼を失い、計画通りに何も進まないことに腹を立てる。

それを避けるには?

現実を直視しよう-スキップできないものもある。プロジェクトの初期に特定のテクノロジーを選択した場合、時間とともにサポートが終了したり、徐々に時代遅れになりつつある数年前のテクノロジーに精通するプログラマーが少なくなっていくことを意識しなければならない。ライブラリのアップデートによっては、多かれ少なかれコードの変更が必要になり、依存関係の渦に巻き込まれ、さらに身動きが取れなくなることがよくある。

もちろん、テクノロジーは古くなっていくが、それらを含むプロジェクトの開発時間を確実に遅らせる要因は、大部分が醜いコードである。もちろん、ここでロバート・C・マーティンの本について触れなければならない。これはプログラマーにとってのバイブルであり、著者は完璧を目指すコードを作るために従うべき優れたプラクティスと原則を数多く提示している。

  1. 変数の名前をつけるときに基本的なことは、その意図を明確かつシンプルに伝えることである。とても簡単なことのように聞こえますが、多くの人が軽視したり無視したりしていることがあります。良い名前は、その変数が何を格納するのか、あるいは関数が何をするのかを明確にする。良質なコードをしばらく使っていると、私たちは無意識のうちに、どんな意図で関数を動かし、関数を呼び出したらどんな結果が期待されるのか、錯覚することのないように、命名や関数へのデータの受け渡しをアレンジできるようになる。
  2. もうひとつは JavaScriptとりわけ、コードを過剰に最適化しようとする試みは、多くの場合、コードを読めなくしてしまう。アルゴリズムによっては特別な注意が必要なものがあるのは普通のことで、それはコードの意図が少し複雑になりやすいという事実を反映していることが多い。とはいえ、過剰な最適化が必要なケースは極めて稀で、少なくともコードが汚れているようなケースだ。例えば、V8エンジンは十分な反復を行うことで、ループを大幅に高速化することができる。強調すべきは、我々は21世紀に生きており、アポロ13号のミッションのためにプログラムを書いているわけではないという事実である。リソースは(できれば合理的な方法で)使われるためにあるのだ。
  3. コードを部分的に分割することで、多くのことが見えてくることがある。操作が連鎖していて、その目的がデータの特定の変更を担当するアクションを実行することである場合、迷子になるのは簡単だ。そのため、単純な方法として、すべてを1つの文字列で行うのではなく、特定のことを担当するコードの個々の部分を個々の要素に分解することができる。こうすることで、個々の操作の意図が明確になるだけでなく、1つのことだけを担当するコード断片をテストすることができ、簡単に再利用できるようになります。

実例

この段落では、多かれ少なかれ良いものに変えることができる、いくつかの悪いコード・プラクティスを概説してみようと思う。この段落では、多かれ少なかれ良いものに変えることができる、いくつかの悪いコード・プラクティスを概説してみようと思う。

一文字変数の悩みの種

残念なことに、大学でさえもごく一般的に行われている恐ろしい習慣が、変数名を1文字で表すことだ。変数の目的を判断するための不必要な思考を避け、変数名に複数の文字を使う代わりに、例えばi、j、kのように1文字で済ませるのである。

逆説的だが、これらの変数の定義の中には、著者が何を考えていたかを決定する、もっと長いコメントが付けられているものもある。

ここでの良い例は、列と行の交点に対応する値を含む2次元配列に対する反復を表現することである。

const array = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];

// かなり悪い
for (let i = 0; i < array[i]; i++) { { { for (let j = 0; j < array[i][j]; j++)
  for (let j = 0; j < array[i][j]; j++) { // ここに内容がある。
    // これがその内容だが、iとjが使われるたびに、それが何に使われているかを分析しなければならない。
  }


// まだ悪いが、面白い
let i; // 行
let j; // 列

for (i = 0; i < array[i]; i++) { // 行を指定する。
  for (j = 0; j < array[i][j]; j++) { // ここに内容がある。
    // しかし、iとjが使われるたびに、それが何に使われているのかコメントをチェックしなければならない。
  }


// はるかに良い
const rowCount = array.length;

for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { {.
  const row = array[rowIndex];
  const columnCount = row.length;

  
    const column = row[columnIndex];

    // 何が何だかわからない人はいないよね?
  }

卑劣な過剰最適化

ある晴れた日、私はある人物が書いた高度に洗練されたコードに出くわした。 ソフトウェアエンジニア.このエンジニアは、ユーザーパーミッションを特定のアクションを指定する文字列として送信する場合、いくつかのビットレベルのトリックを使うことで大幅に最適化できることを突き止めた。

おそらく、ターゲットがコモドール64であれば、このような解決策でも問題ないだろうが、このコードの目的はJSで書かれたシンプルなウェブ・アプリケーションである。この癖を克服する時が来た:
ユーザーがコンテンツを変更するためのオプションは、システム全体で4つしかないとしよう。これらのパーミッションを、ステートを持つオブジェクトのキーか配列としてJSON形式で送信するのは、ごく自然なことだ。

しかし、私たちの賢いエンジニアは、4という数字が2進法におけるマジック・バリューであることに気づき、次のように計算した:

悪いコードの癖

全能力表は16行あるが、これらのパーミッションを作成するアイデアを伝えるために4つだけリストアップした。パーミッションの読み方は以下の通り:

const user = { permissions:11 };

const canCreate = Boolean(user.permissions & 8); // true
const canRead = Boolean(user.permissions & 4); // false
const canUpdate = Boolean(user.permissions & 2); // true
const canDelete = Boolean(user.permissions & 1); // true

上に表示されているのは WebAssemblyコード.ここで誤解されたくないのは、このような最適化は、ある特定のことがごくわずかな時間やメモリ(あるいはその両方)で済む必要のあるシステムでは普通のことだということだ。一方、ウェブアプリケーションは、そのような過剰な最適化がまったく意味をなさない場所であることは間違いない。一般化したくはないが、フロントエンド開発者の仕事では、ビットの抽象化レベルに達するような複雑な操作はめったに行われない。

このようなコードを分析できるプログラマーは、この解決策にはどのような目に見えない利点があるのだろうか? 開発チーム より合理的な解決策に書き換えたい。

しかも、パーミッションを普通のオブジェクトとして送信すれば、プログラマーは1~2秒でインテントを読み取ることができるだろう。プロジェクトには何人かのプログラマーがいるはずで、それぞれがこのコードの断片に出くわさなければならない。その数バイトを保存する価値があるのだろうか?私の考えでは、ノーだ。

分割統治

ウェブ開発 は急速に成長しており、この点に関してすぐに何かが変わるという兆候はない。最近、フロントエンド開発者の責任が大幅に増加したことは認めざるを得ない。彼らは、ユーザーインターフェイスにおけるデータのプレゼンテーションを担当するロジックの一部を引き継いだのだ。

このロジックが単純で、APIによって提供されるオブジェクトが単純で読みやすい構造を持っていることもある。しかし時には、ページ上のさまざまな場所に適応させるために、さまざまなタイプのマッピングやソートなどの操作が必要になる。そして、ここが沼にはまりやすい場所なのだ。

私は何度も、実行中の操作のデータを事実上読めなくしていることに気づいた。配列メソッドを正しく使い、適切な変数名をつけているにもかかわらず、ある時点での操作の連鎖は、私が達成したかったことの文脈を失いかけていた。また、これらの操作のいくつかは、時には別の場所で使う必要があり、時にはテストを書かなければならないほどグローバルだったり、高度だったりした。

const devices = [
  { id: '001', version: 1, owner: { location: 'Texas', age: 21 }.},
  { id: '002', version: 2, owner: { location: 'Texas', age: 27 }.},
  { id: '003', version: 3, owner: { location: 'Arizona', age: 27 }.},
  { id: '004', version: 2, owner: { location: 'Chicago', age: 24 }.},
  { id: '005', version: 2, owner: { location: 'Arizona', age: 19 }.},
  { id: '006', version: 3, owner: { location: 'Texas', age: 42 }.},
];

// かなり複雑
(() => {
  const locationAgeMap = devices
    .map(device => device.owner)
    .reduce((マップ, アイテム) => { { もし!
      if (!map[item.location]){。
        map[item.location] = item.age;
      } else {
        map[item.location] += item.age;
      }

      return map;
    }, {});

  const locationLegalAgeOwnersMap = devices
    .map(device => device.owner)
    .filter(owner => owner.age >= 21)
    .reduce((マップ, アイテム) => {
      もし(!map[item.location]){なら
        map[item.location] = [item];
      } else {
        map[item.location].push(item);
      }

      return map;
    }, {});

  console.log({ locationAgeMap, locationLegalAgeOwnersMap });
})();

// まだ複雑だが、よりコンパクトに
(() => {
  const locationOwnersMap = devices
  .map(device => device.owner)
  .reduce((マップ, アイテム) => { { もし!
    if (!map[item.location]){。
      map[item.location] = [item];
    } else {
      map[item.location].push(item);
    }

    return map;
  }, {});

  const locationAgeMap = Object.fromEntries(
    Object.entries(locationOwnersMap).map(([場所, 所有者]) => {)
      const ownersAge = owners.map(owner => owner.age).reduce((a, b) => a + b);

      return [location, ownersAge];
    })
  );

  const locationLegalAgeOwnersMap = Object.fromEntries(
    Object.entries(locationOwnersMap).map(([場所, 所有者]) => {)
      const filteredOwners = owners.filter(owner => owner.age >= 21);

      return [location, filteredOwners];
    }).filter(([_location, owners]) => { オーナー.length > 0
      return owners.length > 0;
    })
  );

  console.log({ locationAgeMap, locationLegalAgeOwnersMap });
})();

これは私が伝えたいことを簡単に説明できるような些細なコードではない。そして、2つの例の計算の複雑さがわずかに異なることも知っている。アルゴリズムの違いは単純で、どちらも場所とデバイスの所有者のマップを用意する。

最初のものはこのマップを2回作成するが、2番目のものは1回しか作成しない。そして、2番目のアルゴリズムの方が移植性が高いことを示す最も単純な例は、1番目のアルゴリズムではこのマップを作成するロジックを変更する必要があり、例えば、特定の場所を除外したり、ビジネスロジックと呼ばれる奇妙なことを行う必要があるという事実にある。つ目のアルゴリズムの場合、マップの取得方法のみを変更し、それ以降の行で発生するデータの変更はすべて変更しない。最初のアルゴリズムの場合、マップを準備するすべての試みに手を加える必要がある。

実際には、アプリケーション全体の特定のデータモデルを変換したり、リファクタリングしたりする必要がある場合、このようなケースはたくさんある。

様々なビジネスの変化に対応し続けることを避ける最善の方法は、かなり汎用的な方法で関心のある情報を抽出できるグローバルツールを準備することである。たとえ、最適化解除の代償として失うかもしれない2-3ミリ秒を犠牲にしても。

概要

プログラマーは他の職業と同じように、毎日新しいことを学び、多くの間違いを犯します。最も重要なことは、これらの間違いから学び、自分の職業でより良くなり、将来そのような間違いを繰り返さないようにすることです。私たちの仕事が常に完璧であるという神話を信じることはできない。しかし、他の人の経験に基づき、欠点を減らすことはできる。

この記事を読むことで、少なくともいくつかのことを避けることができることを願っている。 悪しきコーディング慣行 私が仕事で経験したことベスト・コード・プラクティスに関するご質問は、下記までご連絡ください。 The Codestクルー 疑問点を相談するために。

続きを読む

NextJSのデータフェッチ戦略

ウェブアプリのセキュリティ - XSSの脆弱性

ウェブアプリのセキュリティターゲット="_blank" 脆弱性

*タイトル画像はspeednet.plより

関連記事

ソフトウェア開発

将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察

The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...

ザ・コデスト
ソフトウェア開発

ラトビアを拠点とするソフトウェア開発企業トップ10社

ラトビアのトップソフトウェア開発企業とその革新的なソリューションについて、最新記事でご紹介します。ラトビアの技術リーダーたちがあなたのビジネスをどのように向上させるかをご覧ください。

thecodest
エンタープライズ&スケールアップ・ソリューション

Javaソフトウェア開発の要点:アウトソーシングを成功させるためのガイド

outsourcingのJavaソフトウェア開発を成功させるために不可欠なこのガイドを読んで、The Codestで効率性を高め、専門知識にアクセスし、プロジェクトを成功に導きましょう。

thecodest
ソフトウェア開発

ポーランドにおけるアウトソーシングの究極ガイド

ポーランドのoutsourcingの急増は、経済、教育、技術の進歩がITの成長とビジネス・フレンドリーな環境を促進していることによる。

ザ・コデスト
エンタープライズ&スケールアップ・ソリューション

IT監査ツール&テクニック完全ガイド

IT監査は、安全かつ効率的で、コンプライアンスに準拠したシステムを保証します。その重要性については、記事全文をお読みください。

The Codest
ヤクブ・ヤクボヴィッチ CTO & 共同創設者

ナレッジベースを購読して、IT部門の専門知識を常に最新の状態に保ちましょう。

    会社概要

    The Codest - ポーランドに技術拠点を持つ国際的なソフトウェア開発会社。

    イギリス - 本社

    • オフィス 303B, 182-184 High Street North E6 2JA
      イギリス、ロンドン

    ポーランド - ローカル・テック・ハブ

    • ファブリチュナ・オフィスパーク、アレハ
      ポコジュ18、31-564クラクフ
    • ブレイン・エンバシー, コンストルクトースカ
      11, 02-673 Warsaw, Poland

      The Codest

    • ホーム
    • 会社概要
    • サービス
    • Case Studies
    • ノウハウ
    • 採用情報
    • 辞書

      サービス

    • アドバイザリー
    • ソフトウェア開発
    • バックエンド開発
    • フロントエンド開発
    • Staff Augmentation
    • バックエンド開発者
    • クラウドエンジニア
    • データエンジニア
    • その他
    • QAエンジニア

      リソース

    • 外部ソフトウェア開発パートナーとの協力に関する事実と神話
    • 米国から欧州へ:アメリカの新興企業がヨーロッパへの移転を決断する理由
    • テックオフショア開発ハブの比較:テックオフショア ヨーロッパ(ポーランド)、ASEAN(フィリピン)、ユーラシア(トルコ)
    • CTOとCIOの課題は?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • ウェブサイト利用規約

    著作権 © 2025 by The Codest。無断複写・転載を禁じます。

    jaJapanese
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek jaJapanese