Skip to content

FahmidAnabi/clean-code-javascript

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

clean-code-javascript

সুচিপত্র

  1. পরিচিতি
  2. ভ্যারিয়েবল
  3. ফাংশন
  4. Objects and Data Structures
  5. Classes
  6. SOLID
  7. Testing
  8. Concurrency
  9. Error Handling
  10. Formatting
  11. Comments
  12. Translation

পরিচিতি

Humorous image of software quality estimation as a count of how many expletives you shout when reading code

সফটওয়্যার ইঞ্জিনিয়ারিং প্রিন্সিপাল Robert C. Martin এর বই Clean Code থেকে জাভাস্ক্রিপ্টের জন্য নেওয়া হয়েছে। এটি কোন স্টাইল গাইড নয়। এই গাইডটি জাভাস্ক্রিপ্ট দিয়ে readable, reusable, এবং refactorable সফটওয়্যার বানাতে সহয়তা করবে।

ভ্যারিয়েবল

অর্থপূর্ণ এবং উচ্চারণযোগ্য ভ্যারিয়েবল নাম ব্যবহার করা উচিৎ

খারাপ:

const yyyymmdstr = moment().format("YYYY/MM/DD");

ভালো:

const currentDate = moment().format("YYYY/MM/DD");

⬆ উপরে যাও

ভ্যারিয়েবলের টাইপ অনুযায়ী একই ধরণের নাম ব্যবহার করা উচিৎ

খারাপ:

getUserInfo();
getClientData();
getCustomerRecord();

ভালো:

getUser();

⬆ উপরে যাও

সহজেই খুঁজে পাওয়া যায় এমন নাম ব্যবহার করা উচিৎ

আমরা জীবনে যতটা না কোড লিখব তার চেয়েও বেশি কোড পড়ব। এটি অত্যন্ত গুরুত্বপূর্ণ, যে কোডটি আমরা লিখব সেটা যেন পড়ার উপযুক্ত এবং অনুসন্ধানযোগ্য হয়। আমাদের প্রোগ্রাম বোঝার জন্য অর্থপূর্ণ ভ্যারিয়েবল নাম ব্যবহার না করে, আমরা আমাদের পাঠকদের যন্ত্রণা এবং কষ্ট দেই। এজন্য ভ্যারিয়েবলের নামগুলি অনুসন্ধানযোগ্য করুন। buddy.js এবং ESLint এর মতো টুলসগুলো নাম ছাড়া ভেরিয়েবল সনাক্ত করতে সহায়তা করতে পারে।

খারাপ:

// What the heck is 86400000 for?
setTimeout(blastOff, 86400000);

ভালো:

// Declare them as capitalized named constants.
const MILLISECONDS_IN_A_DAY = 86400000;

setTimeout(blastOff, MILLISECONDS_IN_A_DAY);

⬆ উপরে যাও

অর্থপ্রকাশক বা ব্যাখ্যামূলক ভ্যারিয়েবল নাম ব্যবহার করা উচিৎ

খারাপ:

const address = "One Infinite Loop, Cupertino 95014";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(
  address.match(cityZipCodeRegex)[1],
  address.match(cityZipCodeRegex)[2]
);

ভালো:

const address = "One Infinite Loop, Cupertino 95014";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);

⬆ উপরে যাও

আধ্যাত্মিক ম্যাপিং এড়িয়ে চলুন

ঊহ্য এর চেয়ে পরিষ্কারভাবে বর্ণিত বেশী ভালো।

খারাপ:

const locations = ["Austin", "New York", "San Francisco"];
locations.forEach(l => {
  doStuff();
  doSomeOtherStuff();
  // ...
  // ...
  // ...
  // Wait, what is `l` for again?
  dispatch(l);
});

ভালো:

const locations = ["Austin", "New York", "San Francisco"];
locations.forEach(location => {
  doStuff();
  doSomeOtherStuff();
  // ...
  // ...
  // ...
  dispatch(location);
});

⬆ উপরে যাও

অপ্রয়োজনীয় কনটেক্সট যুক্ত করবেন না

যদি আপনার ক্লাস/অবজেক্ট এর নামেই কোন কিছু প্রকাশ করে, তাহলে সেই একই জিনিস ভ্যারিয়েবলের নামে ব্যবহার করবেন না।

খারাপ:

const Car = {
  carMake: "Honda",
  carModel: "Accord",
  carColor: "Blue"
};

function paintCar(car) {
  car.carColor = "Red";
}

ভালো:

const Car = {
  make: "Honda",
  model: "Accord",
  color: "Blue"
};

function paintCar(car) {re often cleaner than short circuiting. Be aware that if you
use them
  car.color = "Red";
}

⬆ উপরে যাও

শর্ট সার্কুটিং বা কন্ডিশনালের পরিবর্তে ডিফল্ট আর্গুমেন্ট ব্যবহার করুন

ডিফল্ট আর্গুমেন্ট প্রায়শই শর্ট সার্কুটিং এর চেয়ে পরিষ্কার। সচেতন থাকবেন যদি আপনি শর্ট সার্কুটিং ব্যবহার করে থাকেন, আপনার ফাংশনটি কেবল undefined আর্গুমেন্টের জন্যই ডিফল্ট ভ্যালু প্রদান করবে। অন্যান্য “ফলসি” ভ্যালু যেমন '', "", false, null, 0, and NaN এর জন্য ডিফল্ট ভ্যালু দ্বারা প্রতিস্থাপিত হবে না।

খারাপ:

function createMicrobrewery(name) {
  const breweryName = name || "Hipster Brew Co.";
  // ...
}

ভালো:

function createMicrobrewery(name = "Hipster Brew Co.") {
  // ...
}

⬆ উপরে যাও

ফাংশন

ফাংশন আর্গুমেন্ট (২ অথবা তার চেয়ে কম)

ফাংশন প্যারামিটারের সংখ্যা সীমাবদ্ধে রাখা অত্যন্ত গুরুত্বপূর্ণ, কারণ এতে ফাংশনটিকে পরীক্ষা করা অধিকর সহজ হয়ে যায়। তিনটিরও বেশি সংখ্যক প্যারামিটার একত্রিত হলে বিস্ফোরণের দিকে যাবে, যেখানে আপনাকে বিভিন্ন সংখ্যক কেস পরীক্ষা করতে হবে প্রতিটি আর্গুমেন্ট এর জন্য।

এক্ষেত্রে এক বা দুটি আর্গুমেন্ট হল আদর্শ এবং তিনটি যত সম্ভব এড়ানো উচিত, এর চেয়ে বেশি হলে একত্র করা উচিত। সাধারণত, আপনার যদি দুটিরও বেশি আর্গুমেন্ট থাকে তবে আপনার ফাংশনটি অনেক বেশি কাজ করার চেষ্টা করে। যেক্ষেত্রে এমন হয় না, সেক্ষেত্রে প্রায়শই হাই লেভেলের অবজেক্ট আর্গুমেন্ট হিসেবে কাজ করে।

যেহেতু অনেকগুলো ক্লাস বয়লারপ্লেট ছাড়াই জাভাস্ক্রিপ্ট আপনাকে এমনিতেই অবজেক্ট তৈরি করতে দেয়, যদি আপনার অনেক বেশি আর্গুমেন্ট এর দরকার হয়ে থাকে তাহলে আর্গুমেন্ট হিসেবে আপনি একটি অবজেক্ট ব্যবহার করতে পারেন।

ফাংশনটি কী কী বৈশিষ্ট্য প্রত্যাশা করে তা স্পষ্ট করে তুলতে, আপনি ES2015/ES6 ডেস্ট্রাকচারিং সিনট্যাক্স ব্যবহার করতে পারেন। এর কয়েকটি সুবিধা রয়েছে:

  1. যখন কেউ ফাংশনটিকে দেখবে, এটি সাথেসাথে কি কি প্রোপার্টি ব্যবহার করা হয়েছে তা বলে দিবে।
  2. ডেস্ট্রাকচারিং ফাংশনে প্রেরণ করা আর্গুমেন্টের নির্দিষ্ট প্রিমিটিভ ভ্যালু গুলিও ক্লোন করে। এটি পার্শ্ব প্রতিক্রিয়া রোধ করতে সহায়তা করতে পারে। বি.দ্রঃ অবজেক্ট এবং অ্যারে যেগুলো আর্গুমেন্ট অবজেক্ট হতে ডেস্ট্রাকচার্ড সেগুলো ক্লোন করা হয় না।
  3. লিন্টারগুলো অব্যবহৃত প্রোপার্টি সম্পর্কে সতর্ক করতে পারে, যেটা ডেস্ট্রাকচারিং ছাড়া অসম্ভব হবে।

খারাপ:

function createMenu(title, body, buttonText, cancellable) {
  // ...
}

ভালো:

function createMenu({ title, body, buttonText, cancellable }) {
  // ...
}

createMenu({
  title: "Foo",
  body: "Bar",
  buttonText: "Baz",
  cancellable: true
});

⬆ উপরে যাও

ফাংশনের একটি জিনিস করা উচিত

এটি এখন পর্যন্ত সফ্টওয়্যার ইঞ্জিনিয়ারিংয়ের সবচেয়ে গুরুত্বপূর্ণ নিয়ম। ফাংশনগুলি যখন একাধিক জিনিস করে তখন এদের কম্পোস এবং টেস্ট করা অনেক কঠিন হয়ে যায়। আপনি যখন কেবল একটি কাজে কোন ফাংশনকে আলাদা করতে পারেন, তখন এগুলি সহজেই রিফ্যাক্টর করা যায় এবং আপনার কোডটি আরও পরিষ্কার পরিচ্ছন্ন থাকবে। আপনি যদি এই ছাড়া অন্য কিছু এই গাইড থেকে না নিয়েও থাকেন, এরপরেও অনেক ডেভলপার হতে আপনি এগিয়ে থাকবেন।

খারাপ:

function emailClients(clients) {
  clients.forEach(client => {
    const clientRecord = database.lookup(client);
    if (clientRecord.isActive()) {
      email(client);
    }
  });
}

ভালো:

function emailActiveClients(clients) {
  clients.filter(isActiveClient).forEach(email);
}

function isActiveClient(client) {
  const clientRecord = database.lookup(client);
  return clientRecord.isActive();
}

⬆ উপরে যাও

ফাংশন যা কাজ করে সেটাই নাম হওয়া উচিৎ

খারাপ:

function addToDate(date, month) {
  // ...
}

const date = new Date();

// It's hard to tell from the function name what is added
addToDate(date, 1);

ভালো:

function addMonthToDate(month, date) {
  // ...
}

const date = new Date();
addMonthToDate(1, date);

⬆ উপরে যাও

ফাংশনগুলোতে শুধুমাত্র এক স্তরের অ্যাবস্ট্রাকশন থাকা উচিৎ

যখন আপনার একাধিক স্তরের অ্যাবস্ট্রাকশন থাকে তখন আপনার ফাংশনটি সাধারণত খুব বেশি কাজ করে। ফাংশনগুলি বিভক্ত করলে পুনরায় ব্যবহারযোগ্যতা এবং সহজেই টেস্ট করার দিকে ধাবিত করে।

খারাপ:

function parseBetterJSAlternative(code) {
  const REGEXES = [
    // ...
  ];

  const statements = code.split(" ");
  const tokens = [];
  REGEXES.forEach(REGEX => {
    statements.forEach(statement => {
      // ...
    });
  });

  const ast = [];
  tokens.forEach(token => {
    // lex...
  });

  ast.forEach(node => {
    // parse...
  });
}

ভালো:

function parseBetterJSAlternative(code) {
  const tokens = tokenize(code);
  const syntaxTree = parse(tokens);
  syntaxTree.forEach(node => {
    // parse...
  });
}

function tokenize(code) {
  const REGEXES = [
    // ...
  ];

  const statements = code.split(" ");
  const tokens = [];
  REGEXES.forEach(REGEX => {
    statements.forEach(statement => {
      tokens.push(/* ... */);
    });
  });

  return tokens;
}

function parse(tokens) {
  const syntaxTree = [];
  tokens.forEach(token => {
    syntaxTree.push(/* ... */);
  });

  return syntaxTree;
}

⬆ উপরে যাও

ডুপ্লিকেট কোড রিমুভ করতে হবে

ডুপ্লিকেট কোড এড়াতে আপনার সর্বোচ্চ চেষ্টা করুন। ডুপ্লিকেট কোড অত্যন্ত খারাপ কারণ কোথাও কোন লজিক পরিবর্তন করতে হলে অনেক জায়গার লজিক/কোড পরিবর্তন করতে হবে।

কল্পনা করুন আপনি কোনও রেস্তোরাঁ চালাচ্ছেন এবং নিজেই বাজারের তালিকা ট্র্যাক করেনঃ আপনার সকল টমেটো, পেঁয়াজ, রসুন, মশলা ইত্যাদি। আপনার যদি এমন একাধিক তালিকা থাকে যা আপনি ট্রাক রাখেন, যখন আপনি টমেটো দিয়ে কোন খাবার পরিবেশন করবেন তখন আপনাকে সকল তালিকা আপডেট করতে হবে। যদি আপনার কেবল একটিই তালিকা থাকে তাহলে কেবলমাত্র একটি জায়গায় আপডেট করলেই হবে।

খারাপ:

function showDeveloperList(developers) {
  developers.forEach(developer => {
    const expectedSalary = developer.calculateExpectedSalary();
    const experience = developer.getExperience();
    const githubLink = developer.getGithubLink();
    const data = {
      expectedSalary,
      experience,
      githubLink
    };

    render(data);
  });
}

function showManagerList(managers) {
  managers.forEach(manager => {
    const expectedSalary = manager.calculateExpectedSalary();
    const experience = manager.getExperience();
    const portfolio = manager.getMBAProjects();
    const data = {
      expectedSalary,
      experience,
      portfolio
    };

    render(data);
  });
}

ভালো:

function showEmployeeList(employees) {
  employees.forEach(employee => {
    const expectedSalary = employee.calculateExpectedSalary();
    const experience = employee.getExperience();

    const data = {
      expectedSalary,
      experience
    };

    switch (employee.type) {
      case "manager":
        data.portfolio = employee.getMBAProjects();
        break;
      case "developer":
        data.githubLink = employee.getGithubLink();
        break;
    }

    render(data);
  });
}

⬆ উপরে যাও

Set default objects with Object.assign

খারাপ:

const menuConfig = {
  title: null,
  body: "Bar",
  buttonText: null,
  cancellable: true
};

function createMenu(config) {
  config.title = config.title || "Foo";
  config.body = config.body || "Bar";
  config.buttonText = config.buttonText || "Baz";
  config.cancellable =
    config.cancellable !== undefined ? config.cancellable : true;
}

createMenu(menuConfig);

ভালো:

const menuConfig = {
  title: "Order",
  // User did not include 'body' key
  buttonText: "Send",
  cancellable: true
};

function createMenu(config) {
  config = Object.assign(
    {
      title: "Foo",
      body: "Bar",
      buttonText: "Baz",
      cancellable: true
    },
    config
  );

  // config now equals: {title: "Order", body: "Bar", buttonText: "Send", cancellable: true}
  // ...
}

createMenu(menuConfig);

⬆ উপরে যাও

ফাংশন প্যারামিটার হিসেবে ফ্ল্যাগ ব্যবহার করা উচিৎ নয়

ফ্ল্যাগ ব্যবহারকারীকে নির্দেশনা দেয় যে এই ফাংশন একাধিক কাজ করে। ফাংশনের শুধুমাত্র একটি কাজ করা উচিৎ। আপনার ফাংশনগুলি আলাদা করুন যদি তারা কোন বুলিয়ানের উপর ভিত্তি করে ভিন্ন কোড পাথ অনুসরণ করে।

খারাপ:

function createFile(name, temp) {
  if (temp) {
    fs.create(`./temp/${name}`);
  } else {
    fs.create(name);
  }
}

ভালো:

function createFile(name) {
  fs.create(name);
}

function createTempFile(name) {
  createFile(`./temp/${name}`);
}

⬆ উপরে যাও

পার্শ্ব প্রতিক্রিয়া এড়িয়ে চলুন (প্রথম অংশ)

একটি ফাংশন তখনই কোন পার্শ্ব প্রতিক্রিয়া তৈরি করে যখন এটি একটি ভ্যালু গ্রহণ করে এবং অন্য ভ্যালু বা একের অধিক ভ্যালু রিটার্ন করে। পার্শ্ব প্রতিক্রিয়া যে কোন কিছু হতে পারে। যেমনঃ কোন ফাইলে লেখা, গ্লোবাল ভ্যারিয়েবলের পরিবর্তন অথবা দুর্ঘটনাক্রমে আপনার সমস্ত টাকা কোন অপরিচিত ব্যক্তিকে পাঠিয়ে দেওয়া ইত্যাদি।

এখন, আপনার বিশেষ উপলক্ষে আপনার প্রোগ্রামে পার্শ্ব প্রতিক্রিয়া থাকা দরকার। পূর্ববর্তী উদাহরণের মতো, আপনার হয়ত কোন ফাইল লিখতে হবে। আপনি এখন যা করতে চান তা হল, আপনি যেখানে এটি করছেন সেটা একত্রিত করা। একটি নির্দিষ্ট ফাইলে লেখার জন্য বেশ কয়েকটি ফাংশন এবং ক্লাস নেই। একটি ফাংশন আছে যেটা এই কাজ করে এবং কেবল মাত্র একটিই ফাংশন।

মূল বিষয় হচ্ছে কোনও কাঠামো ছাড়াই অবজেক্টের মধ্যে স্টেট ভাগ করে নেওয়ার মতো সাধারণ সমস্যাগুলি এড়াতে চলা, পরিবর্তনীয় ডেটা টাইপ ব্যবহার করা যা কোন কিছু দ্বারা লেখা যাবে এবং আপনি অন্যান্য সংখ্যাগরিষ্ঠ প্রোগ্রামারদের চেয়ে সুখী থাকবেন।

খারাপ:

// Global variable referenced by following function.
// If we had another function that used this name, now it'd be an array and it could break it.
let name = "Ryan McDermott";

function splitIntoFirstAndLastName() {
  name = name.split(" ");
}

splitIntoFirstAndLastName();

console.log(name); // ['Ryan', 'McDermott'];

ভালো:

function splitIntoFirstAndLastName(name) {
  return name.split(" ");
}

const name = "Ryan McDermott";
const newName = splitIntoFirstAndLastName(name);

console.log(name); // 'Ryan McDermott';
console.log(newName); // ['Ryan', 'McDermott'];

⬆ উপরে যাও

পার্শ্ব প্রতিক্রিয়া এড়িয়ে চলুন (দ্বিতীয় অংশ)

জাভাস্ক্রিপ্টে প্রিমিটিভগুলো ভ্যালু এবং অবজেক্ট/অ্যারে গুলো রেফারেন্স দিয়ে পাস হয়। অবজেক্ট এবং অ্যারের ক্ষেত্রে,যদি আপনার ফাংশন কোনও শপিং কার্ট অ্যারে পরিবর্তন করে উদাহরণ্বরূপঃ কেনার জন্য একটি আইটেম এড করলে cart অ্যারে ব্যবহার করা অন্য কোন ফাংশনও এই সংযোজন দ্বারা প্রভাবিত হবে। এটি দুর্দান্ত হতে পারে, তবে এটি খারাপও হতে পারে।

খারাপ:

const addItemToCart = (cart, item) => {
  cart.push({ item, date: Date.now() });
};

ভালো:

const addItemToCart = (cart, item) => {
  return [...cart, { item, date: Date.now() }];
};

⬆ উপরে যাও

গ্লোবাল ফাংশনে লিখবেন না

জাভাস্ক্রিপ্টে গ্লোবাল কোন কিছু ্ নষ্ট করা বা পরিবর্তন করা অত্যন্ত খারাপ প্রাকটিস কারণ আপনি অন্য একটি লাইব্রেরির সঙ্গে ক্লাস ঘটাতে পারেন এবং আপনার API ব্যবহারকারীরা ততক্ষণ পর্যন্ত টের পাবে না যতক্ষণ না তারা কোন ব্যতিক্রম কিছু লক্ষ্য করবে। একটি উদাহরণ সম্পর্কে চিন্তা করা যাক: ধরে নেন আপনি জাভাস্ক্রিপ্টের একটা নেটিভ অ্যারে মেথডকে এক্সটেন্ড করতে চান যেন সেখানে আরেকটি diff নামের মেথড থাকে যেটি দুটি অ্যারের মধ্যে পার্থক্য দেখাতে পারে। আপনি চাইলে Array.prototype-এ একটি নতুন ফাংশন লিখতে পারেন কিন্তু এতে অন্য কোন লাইব্রেরির সাথে সংঘর্ষ হতে পারে যারা একই কাজ করে। তখন কি হবে যদি আরেকটি লাইব্রেরি diff ব্যবহার করত শুধুমাত্র একটি অ্যারের প্রথম এবং শেষ ইলিমেন্টের মধ্যে পার্থক্য বের করার জন্য? এজন্যই ES2015/ES6 ক্লাস ব্যবহার করা আরও ভাল হবে এবং এটা সিম্পলি গ্লোবাল Array এক্সটেন্ড করবে।

খারাপ:

Array.prototype.diff = function diff(comparisonArray) {
  const hash = new Set(comparisonArray);
  return this.filter(elem => !hash.has(elem));
};

ভালো:

class SuperArray extends Array {
  diff(comparisonArray) {
    const hash = new Set(comparisonArray);
    return this.filter(elem => !hash.has(elem));
  }
}

⬆ উপরে যাও

ফাংশনাল প্রোগ্রামিংকে ইমপারেটিভ প্রোগ্রামিং থেকে বেশি গুরুত্ব দিন

JavaScript isn't a functional language in the way that Haskell is, but it has a functional flavor to it. Functional languages can be cleaner and easier to test. Favor this style of programming when you can.য়া

খারাপ:

const programmerOutput = [
  {
    name: "Uncle Bobby",
    linesOfCode: 500
  },
  {
    name: "Suzie Q",
    linesOfCode: 1500
  },
  {
    name: "Jimmy Gosling",
    linesOfCode: 150
  },
  {
    name: "Gracie Hopper",
    linesOfCode: 1000
  }
];

let totalOutput = 0;

for (let i = 0; i < programmerOutput.length; i++) {
  totalOutput += programmerOutput[i].linesOfCode;
}

ভালো:

const programmerOutput = [
  {
    name: "Uncle Bobby",
    linesOfCode: 500
  },
  {
    name: "Suzie Q",
    linesOfCode: 1500
  },
  {
    name: "Jimmy Gosling",
    linesOfCode: 150
  },
  {
    name: "Gracie Hopper",
    linesOfCode: 1000
  }
];

const totalOutput = programmerOutput.reduce(
  (totalLines, output) => totalLines + output.linesOfCode,
  0
);

⬆ উপরে যাও

Encapsulate conditionals

খারাপ:

if (fsm.state === "fetching" && isEmpty(listNode)) {
  // ...
}

ভালো:

function shouldShowSpinner(fsm, listNode) {
  return fsm.state === "fetching" && isEmpty(listNode);
}

if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
  // ...
}

⬆ উপরে যাও

Avoid negative conditionals

খারাপ:

function isDOMNodeNotPresent(node) {
  // ...
}

if (!isDOMNodeNotPresent(node)) {
  // ...
}

ভালো:

function isDOMNodePresent(node) {
  // ...
}

if (isDOMNodePresent(node)) {
  // ...
}

⬆ উপরে যাও

Avoid conditionals

This seems like an impossible task. Upon first hearing this, most people say, "how am I supposed to do anything without an if statement?" The answer is that you can use polymorphism to achieve the same task in many cases. The second question is usually, "well that's great but why would I want to do that?" The answer is a previous clean code concept we learned: a function should only do one thing. When you have classes and functions that have if statements, you are telling your user that your function does more than one thing. Remember, just do one thing.

খারাপ:

class Airplane {
  // ...
  getCruisingAltitude() {
    switch (this.type) {
      case "777":
        return this.getMaxAltitude() - this.getPassengerCount();
      case "Air Force One":
        return this.getMaxAltitude();
      case "Cessna":
        return this.getMaxAltitude() - this.getFuelExpenditure();
    }
  }
}

ভালো:

class Airplane {
  // ...
}

class Boeing777 extends Airplane {
  // ...
  getCruisingAltitude() {
    return this.getMaxAltitude() - this.getPassengerCount();
  }
}

class AirForceOne extends Airplane {
  // ...
  getCruisingAltitude() {
    return this.getMaxAltitude();
  }
}

class Cessna extends Airplane {
  // ...
  getCruisingAltitude() {
    return this.getMaxAltitude() - this.getFuelExpenditure();
  }
}

⬆ উপরে যাও

Avoid type-checking (part 1)

JavaScript is untyped, which means your functions can take any type of argument. Sometimes you are bitten by this freedom and it becomes tempting to do type-checking in your functions. There are many ways to avoid having to do this. The first thing to consider is consistent APIs.

খারাপ:

function travelToTexas(vehicle) {
  if (vehicle instanceof Bicycle) {
    vehicle.pedal(this.currentLocation, new Location("texas"));
  } else if (vehicle instanceof Car) {
    vehicle.drive(this.currentLocation, new Location("texas"));
  }
}

ভালো:

function travelToTexas(vehicle) {
  vehicle.move(this.currentLocation, new Location("texas"));
}

⬆ উপরে যাও

Avoid type-checking (part 2)

If you are working with basic primitive values like strings and integers, and you can't use polymorphism but you still feel the need to type-check, you should consider using TypeScript. It is an excellent alternative to normal JavaScript, as it provides you with static typing on top of standard JavaScript syntax. The problem with manually type-checking normal JavaScript is that doing it well requires so much extra verbiage that the faux "type-safety" you get doesn't make up for the lost readability. Keep your JavaScript clean, write ভালো tests, and have ভালো code reviews. Otherwise, do all of that but with TypeScript (which, like I said, is a great alternative!).

খারাপ:

function combine(val1, val2) {
  if (
    (typeof val1 === "number" && typeof val2 === "number") ||
    (typeof val1 === "string" && typeof val2 === "string")
  ) {
    return val1 + val2;
  }

  throw new Error("Must be of type String or Number");
}

ভালো:

function combine(val1, val2) {
  return val1 + val2;
}

⬆ উপরে যাও

Don't over-optimize

Modern browsers do a lot of optimization under-the-hood at runtime. A lot of times, if you are optimizing then you are just wasting your time. There are ভালো resources for seeing where optimization is lacking. Target those in the meantime, until they are fixed if they can be.

খারাপ:

// On old browsers, each iteration with uncached `list.length` would be costly
// because of `list.length` recomputation. In modern browsers, this is optimized.
for (let i = 0, len = list.length; i < len; i++) {
  // ...
}

ভালো:

for (let i = 0; i < list.length; i++) {
  // ...
}

⬆ উপরে যাও

Remove dead code

Dead code is just as খারাপ as duplicate code. There's no reason to keep it in your codebase. If it's not being called, get rid of it! It will still be safe in your version history if you still need it.

খারাপ:

function oldRequestModule(url) {
  // ...
}

function newRequestModule(url) {
  // ...
}

const req = newRequestModule;
inventoryTracker("apples", req, "www.inventory-awesome.io");

ভালো:

function newRequestModule(url) {
  // ...
}

const req = newRequestModule;
inventoryTracker("apples", req, "www.inventory-awesome.io");

⬆ উপরে যাও

About

🛁 Clean Code concepts adapted for JavaScript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%