概要
改善されたJavaScriptコーディングルール
-
機能中心の開発:アーキテクチャよりも機能を優先して構築し、小さな機能を組み合わせてより大きな機能を作ります。 (機能をまず、小さいものから、組み合わせ)
-
明確性優先:賢明さよりも明確性を追求し、優雅さを目指します。 (明確>賢い、優雅さを追求)
-
注釈の活用: コードを記述する注釈を積極的に使用します。 (注釈積極活用)
-
非同期処理: 非同期処理が必要な場合は使用しますが、同期/非同期の両方が正しく動作する必要があります。 (非同期必要時使用、同期/非同期共に動作)
-
テストベースの開発:テストを活用してコードの安定性を確保します。 (テスト活用)
-
可読性優先: コードの読みやすさを最優先事項として考えます。 (可読性の重要)
-
明示的なコード: 暗黙的なものよりも明示的なコードを記述します。 (明示的>暗黙的)
-
シンプルさの追求: 複雑さよりもシンプルさを追求します。 (単純>複雑)
-
簡潔な構造:入れ子構造よりも平面的な構造を好みます。 (平面 > 入れ子)
-
希少性維持: 密なコードよりも希少なコードを維持します。 (希少>密)
-
例外処理: エラーは明確に処理し、意図的に沈黙させない限り無視しません。 (エラークリア処理、サイレントX)
-
曖昧さ回避: あいまいな状況から推測せず、明確な解決策を探します。 (曖昧さ回避、明確な解決)
-
単一方法: 問題を解決する明確で単一の方法を追求します。 (単一方法を追求)
-
実用性優先:純粋さよりも実用性を優先します。 (実用 > 純粋)
-
ネームスペースの活用: ネームスペースを積極的に活用してコードのモジュール性を高めます。 (名前空間積極活用)
-
良いコードの基準: 実装を説明しやすい場合は、良いコードである可能性が高いです。 (説明しやすいコード)
-
特別な場合の慎重な判断:特別な場合が規則を破るのに十分な特別なものであることを慎重に判断します。
##詳細
- 機能中心の開発:
// 小さな機能:数値配列で偶数のみをフィルタリングする
function filterEvenNumbers(numbers) {
return numbers.filter(number => number % 2 === 0);
}
// 小さな機能:数値配列の各数値を2乗
function squareNumbers(numbers) {
return numbers.map(number => number * number);
}
// より大きな機能:数値配列から偶数だけ二乗して返す(小さな機能の組み合わせ)
function processEvenNumbers(numbers) {
const evenNumbers = filterEvenNumbers(numbers);
return squareNumbers(evenNumbers);
}
// 使用例
const numbers = [1, 2, 3, 4, 5, 6];
const result = processEvenNumbers(numbers);
console.log(result); // [4, 16, 36]
- 明確性優先:
// 明確ではないコード
function calculate(a, b, c) {
return(a+b)*c;
}
// 明確なコード
function calculateSumAndMultiply(firstNumber, secondNumber, multiplier) {
const sum = firstNumber + secondNumber;
return sum * multiplier;
}
// 使用例
const result1 = calculate(2, 3, 4);
const result2 = calculateSumAndMultiply(2, 3, 4);
console.log(result1); // 20
console.log(result2); // 20
- 注釈の活用:
/**
* 2つの数字を加えて返します。
* @param{number} a 加算する最初の数字
* @param{number} b 追加する 2 番目の数字
* @returns{number} 2つの数字の合計
*/
function add(a, b) {
// 関数はここで 2 つの数値を加算します。
return a + b;
}
- 非同期処理:
// 同期関数
function syncOperation(data) {
console.log("同期操作:", data);
return data + "処理完了";
}
// 非同期関数
async function asyncOperation(data) {
console.log("非同期ジョブの開始:", data);
await new Promise(resolve => setTimeout(resolve, 1000));
console.log("非同期操作完了:", data);
return data + "非同期処理完了";
}
// 使用例
syncOperation("データ1");
asyncOperation("データ2").then(result => console.log(result));
- テストベースの開発:
// テスト対象関数
function sum(a, b) {
return a + b;
}
// テスト関数(簡単な例)
function testSum() {
if (sum(2, 3) === 5) {
console.log("テストパス: sum(2, 3) === 5");
}else{
console.error("テストに失敗しました: sum(2, 3) !== 5");
}
if(sum(-1, 1) === 0) {
console.log("テストパス: sum(-1, 1) === 0");
}else{
console.error("テスト失敗: sum(-1, 1) !== 0");
}
}
testSum();
- 可読性優先:
// 読みやすさの低いコード
function f(x,y) {return x*y+x-y}
// 読みやすいコード
function calculateResult(firstNumber, secondNumber) {
const product = firstNumber * secondNumber;
const result = product + firstNumber - secondNumber;
return result
}
- 明示的なコード:
// 暗黙のコード(意味が明確ではない)
function processValue(value) {
if(value){
return value *2;
}
return 0;
}
// 明示的なコード(意味が明確)
function doublePositiveNumber(number) {
if (typeof number === 'number' && number > 0) {
return number *2;
}
return 0;
}
- シンプルさの追求:
// 複雑なロジック(不要な条件文の入れ子)
function check(value) {
if(typeof value === 'number'){
if(value > 0){
if(value % 2 === 0){
return "正と偶数です。"
} else {
return "正と奇数です。"
}
} else {
return "正の数ではありません。"
}
} else {
return "数値ではありません。"
}
}
// 単純なロジック(単一条件文として扱う)
function checkNumber(number){
if(typeof number !== 'number') {
return "数値ではありません。";
}
if(number<=0){
return "正の数ではありません。";
}
return number % 2 === 0 ? "正と偶数です" : "正数で奇数です";
}
- 簡潔な構造:
// 入れ子になった構造(オブジェクト内のオブジェクト)
const nestedObject = {
level1: {
level2: {
level3: 'value'
}
}
};
// フラットな構造
const flatObject = {
'level1.level2.level3': 'value'
};
- 希少性維持:
// 密なコード
const a = 1; const b = 2; const c=3; console.log(a, b, c);
// 希少なコード
const a = 1;
const b = 2;
const c = 3;
console.log(a, b, c);
- 例外処理:
function divide(a, b) {
try {
if (b === 0) {
throw new Error("0 で割り切れません。");
}
return a / b;
} catch(error) {
console.error("エラー発生:", error.message); // エラーロギング
return null; // エラー状況に適した値を返す
}
}
- 曖昧さ回避:
// あいまいなコード(意味が不明)
function process(input) {
if(input) {
return input * 2;
}
return false
}
// 明確なコード(タイプと条件の明確)
function doubleNumberOrReturnFalse(input) {
if(typeof input === 'number') {
return input * 2;
}
return false;
}
- 単一方法:
// 問題を解決するいくつかの方法(混乱の原因)
function sumNumbers1(numbers) {
let total = 0;
for(let i = 0; i < numbers.length; i++) {
total += numbers[i];
}
return total;
}
function sumNumbers2(numbers) {
return numbers.reduce((acc, cur) => acc + cur, 0)
}
// シングルメソッド(reduceを使用)
function sumNumbers(numbers) {
return numbers.reduce((sum, number) => sum + number, 0);
}
- 実用性優先:
// 純粋さを追求したコード
function pureFunction(x) {
return x + 2;
}
// 実用性を追求したコード(必要に応じて副作用を含む)
let counter = 0;
function incrementCounterAndGet(x) {
counter++
console.log('counter value', counter) // 副作用 (console.log)
return x + 2;
}
- ネームスペースの活用:
// ネームスペースなしのグローバルスコープ汚染
const utility1 = {
add: function (a, b) {
return a + b;
}
}
const utility2 = {
add: function (a, b) {
return a + b;
}
}
// 名前空間を活用してモジュール化
const MathUtils = {
add: (a, b) => a + b,
subtract: (a, b) => a - b
};
const StringUtils = {
capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1),
reverse: (str) => str.split("").reverse().join("")
};
- 良いコードの基準:
// 説明が難しいコード(複雑なロジック)
function someFunction(a, b, c, d) {
let result = 0;
if(a > 0){
if(b > 0){
if(c > 0){
result = a + b + c + d;
}
}
}
return result;
}
// 説明しやすいコード
function calculateSumOfPositiveNumbers(a, b, c, d) {
if(a <= 0 || b <= 0 || c <= 0){
return 0;
}
return a + b + c + d;
}
- 特別な場合の慎重な判断:
// 一般的な規則に従うコード
function commonLogic(number) {
return number * 2;
}
// 特別な場合にルールを破るコード(注意が必要)
function specialLogic(number) {
if(number === 0) {
return 0 // 0の特別な処理
}
return number / 2;
}
// 特別なケースを分離して処理
function processNumber(number) {
if(number === 0) {
return 0; // 例外処理
}
return commonLogic(number)
}