1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        一名合格前端工程師必備素質(zhì):代碼整潔之道

        共 22764字,需瀏覽 46分鐘

         ·

        2021-07-13 19:27


        內(nèi)容出自《代碼整潔之道》、Alex Kondov[1]的博文tao-of-react[2]和《Clean Code of Javascript》

        image.png

        代碼整潔有什么用?

        image.png
        1. 思路清晰,降低bug幾率
        2. 更容易維護(hù),利于團(tuán)隊(duì)協(xié)作
        3. 看起來舒服,提高效率
        4. ......

        軟件質(zhì)量與代碼整潔度成正比 --Robert.C.Martin

        軟件設(shè)計(jì)3R層次結(jié)構(gòu):readable, reusable, and refactorable[3] 可讀性、可重用性、可重構(gòu)性

        下面這些原則是作者提出的一些最佳實(shí)踐,但不是強(qiáng)制約束

        關(guān)于命名

        1.使用有意義且易讀的變量名

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

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

        2.使用有意義的變量代替數(shù)組下標(biāo)

        ?? 
        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);

        3.變量名要簡潔,不要附加無用信息

        ?? 
        const Car = {
          carMake: "Honda",
          carModel: "Accord",
          carColor: "Blue"
        };
        function paintCar(car, color{
          car.carColor = color;
        }

        ??
        const Car = {
          make: "Honda",
          model: "Accord",
          color: "Blue"
        };
        function paintCar(car, color{
          car.color = color;
        }

        4.消除魔術(shù)字符串

        ?? setTimeout(blastOff, 86400000);

        ?? const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000//86400000;
        setTimeout(blastOff, MILLISECONDS_PER_DAY);

        5.使用默認(rèn)參數(shù)替代短路運(yùn)算符

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

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

        關(guān)于函數(shù)

        1.一個(gè)函數(shù)只做一件事的好處在于易于理解、易于測(cè)試。

        ??
        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 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}`);
        }

        2.函數(shù)參數(shù)不多于2個(gè),如果有很多參數(shù)就利用object傳遞,并使用解構(gòu)。

        推薦使用解構(gòu)的幾個(gè)原因:

        1. 看到函數(shù)簽名可以立即了解有哪些參數(shù)
        2. 解構(gòu)能克隆傳遞到函數(shù)中的參數(shù)對(duì)象的值(淺克隆),有助于防止副作用.
        3. linter可以提示有哪些參數(shù)未被使用
        ??
        function createMenu(title, body, buttonText, cancellable{
          // ...
        }
        createMenu("Foo""Bar""Baz"true);

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

        3.函數(shù)名應(yīng)該直接反映函數(shù)的作用

        ??
        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);

        4.一個(gè)函數(shù)的抽象層級(jí)不要太多,如果你的函數(shù)做了太多事,就需要把它拆分成多個(gè)函數(shù)

        ??
        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;
        }

        5.減少重復(fù)代碼

        ??
        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);
          });
        }

        6.盡量使用純函數(shù) (函數(shù)式編程,not命令式編程)

        ??
        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
        );

        7.注意函數(shù)的副作用

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

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

        8.不要過度優(yōu)化

        現(xiàn)代瀏覽器在運(yùn)行時(shí)進(jìn)行了大量的優(yōu)化。很多時(shí)候,如果你再優(yōu)化,那就是在浪費(fèi)時(shí)間。

        ??
        // 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++) {
          // ...
        }

        關(guān)于注釋

        1.Comments are an apology, not a requirement. Good code mostly documents itself.

        好的代碼是自注釋的

        ??
        function hashIt(data{
          // The hash
          let hash = 0;

          // Length of string
          const length = data.length;

          // Loop through every character in data
          for (let i = 0; i < length; i++) {
            // Get character code.
            const char = data.charCodeAt(i);
            // Make the hash
            hash = (hash << 5) - hash + char;
            // Convert to 32-bit integer
            hash &= hash;
          }
        }

        ?? 
        function hashIt(data{
          let hash = 0;
          const length = data.length;

          for (let i = 0; i < length; i++) {
            const char = data.charCodeAt(i);
            hash = (hash << 5) - hash + char;

            // Convert to 32-bit integer
            hash &= hash;
          }
        }

        2.git能做的事不要寫在注釋里

        ??
        /**
         * 2016-12-20: Removed monads, didn't understand them (RM)
         * 2016-10-01: Improved using special monads (JP)
         * 2016-02-03: Removed type-checking (LI)
         * 2015-03-14: Added combine with type-checking (JR)
         */

        function combine(a, b{
          return a + b;
        }

        ?? 
        function combine(a, b{
          return a + b;
        }

        關(guān)于組件

        1.盡可能使用函數(shù)組件

        函數(shù)式組件有更簡單的語法,沒有生命周期函數(shù),構(gòu)造函數(shù)。同樣的邏輯和可靠性,函數(shù)式組件可以用更少的代碼完成。

        ?? 
        class Counter extends React.Component {
          state = {
            counter: 0,
          }

          constructor(props) {
            super(props)
            this.handleClick = this.handleClick.bind(this)
          }

          handleClick() {
            this.setState({ counter: this.state.counter + 1 })
          }

          render() {
            return (
              <div>
                <p>counter: {this.state.counter}</p>
                <button onClick={this.handleClick}>Increment</
        button>
              </div>
            )
          }
        }
        ??
        function Counter() {
          const [counter, setCounter] = useState(0)

          handleClick = () => setCounter(counter + 1)

          return (
            <div>
              <p>counter: {counter}</
        p>
              <button onClick={handleClick}>Increment</button>
            </
        div>
          )
        }

        2.函數(shù)組件中剝離邏輯代碼

        盡可能的把邏輯從組件中剝離出去,可以把必要的值用參數(shù)的形式傳給工具類函數(shù)。在函數(shù)組件外組織你的邏輯讓你能夠更簡單的去追蹤 bug 和擴(kuò)展你的功能。

        ??
        export default function Component({
          const [value, setValue] = useState('')

          function isValid({
            // ...
          }

          return (
            <>
              <input
                value={value}
                onChange={e => setValue(e.target.value)}
                onBlur={validateInput}
              />
              <button
                onClick={() => {
                  if (isValid) {
                    // ...
                  }
                }}
              >
                Submit
              </button>
            </
        >
          )
        }

        ?? 
        function isValid(value{
          // ...
        }
        export default function Component({
          const [value, setValue] = useState('')

          return (
            <>
              <input
                value={value}
                onChange={e => setValue(e.target.value)}
                onBlur={validateInput}
              />
              <button
                onClick={() => {
                  if (isValid(value)) {
                    // ...
                  }
                }}
              >
                Submit
              </button>
            </
        >
          )
        }

        3.控制組件長度,減少UI耦合

        函數(shù)組件也是函數(shù),同樣要控制長度,如果組件太長,就要拆成多個(gè)組件

        ??
        function Filters({ onFilterClick }{
          return (
            <>
              <p>Book Genres</p>
              <ul>
                <li>
                  <div onClick={() => onFilterClick('fiction')}>Fiction</
        div>
                </li>
                <li>
                  <div onClick={() => onFilterClick('classics')}>
                    Classics
                  </
        div>
                </li>
                <li>
                  <div onClick={() => onFilterClick('fantasy')}>Fantasy</
        div>
                </li>
                <li>
                  <div onClick={() => onFilterClick('romance')}>Romance</
        div>
                </li>
              </u
        l>
            </>
          )
        }

        /
        / ?? Use loops and configuration objects
        const GENRES = [
          {
            identifier: 'fiction',
            name: Fiction,
          },
          {
            identifier: 'classics',
            name: Classics,
          },
          {
            identifier: 'fantasy',
            name: Fantasy,
          },
          {
            identifier: 'romance',
            name: Romance,
          },
        ]

        function Filters({ onFilterClick }) {
          return (
            <>
              <p>Book Genres</
        p>
              <ul>
                {GENRES.map(genre => (
                  <li>
                    <div onClick={() => onFilterClick(genre.identifier)}>
                      {genre.name}
                    </div>
                  </
        li>
                ))}
              </ul>
            </
        >
          )
        }

        4.盡量避免函數(shù)組件內(nèi)再定義函數(shù)組件

        不要在一個(gè)函數(shù)組件中再去書寫一個(gè)函數(shù)組件。一個(gè)函數(shù)組件應(yīng)該僅僅是一個(gè)函數(shù)。函數(shù)組件內(nèi)部再定義函數(shù)組件,意味著內(nèi)部的函數(shù)組件能夠通過作用域訪問到外層組件所有的 state 和 props,這樣會(huì)使內(nèi)部定義組件不可靠。把內(nèi)部的組件移到外部,避免閉包和作用域的影響。

        // ?? Don't write nested render functions
        function Component({
          function renderHeader({
            return <header>...</header>
          }
          return <div>{renderHeader()}</
        div>
        }
        // ?? Extract it in its own component
        import Header from '@modules/common/components/Header'
        function Component({
          return (
            <div>
              <Header />
            </div>
          )
        }

        5.優(yōu)化props

        控制props數(shù)量、聚合props、完善渲染條件

        1. 如何把控 props 的量是一個(gè)值得商榷的問題。但是一個(gè)組件傳遞越多的 props 意味著它做的事情越多這是共識(shí)。當(dāng) props 達(dá)到一定數(shù)量的時(shí)候,意味著這個(gè)組件做的事情太多了。當(dāng)props的數(shù)量達(dá)到5個(gè)以上的時(shí)候,這個(gè)組件就需要被拆分了。在某些極端諸如輸入類型組件的情況下,可能擁有過多的props,但在通常情況下5個(gè)props能夠滿足大部分組件的需求。

        提示:一個(gè)組件擁有越多的 props,越容易被 rerender。

        1. 一些場(chǎng)景下使用短路語法來進(jìn)行條件渲染可能導(dǎo)致期望之外的問題,有可能會(huì)渲染一個(gè) 0 在界面上。避免這種情況發(fā)生,盡量使用三元操作符。盡管短路操作符能使代碼變得簡潔,但是三元操作符能夠保證渲染的正確性。
        // ?? Try to avoid short-circuit operators
        function Component({
          const count = 0

          return <div>{count && <h1>Messages: {count}</h1>}</div>
        }
        // ?? Use a ternary instead
        function Component({
          const count = 0

          return <div>{count ? <h1>Messages: {count}</h1> : null}</div>
        }

        關(guān)于其他

        1.把組件放入單獨(dú)的文件夾中

        // ?? Don't keep all component files together
        ├── components
            ├── Header.jsx
            ├── Header.scss
            ├── Header.test.jsx
            ├── Footer.jsx
            ├── Footer.scss
            ├── Footer.test.jsx

        // ?? Move them in their own folder
        ├── components
            ├── Header
                ├── index.js
                ├── Header.jsx
                ├── Header.scss
                ├── Header.test.jsx
            ├── Footer
                ├── index.js
                ├── Footer.jsx
                ├── Footer.scss
                ├── Footer.test.jsx

        2.盡量使用絕對(duì)路徑

        使用絕對(duì)路徑可以在移動(dòng)一個(gè)文件的時(shí)候能夠盡量少的更改其它文件。絕對(duì)路徑也能讓你對(duì)所有依賴文件的出處一目了然。

        (完)

        參考文獻(xiàn):《代碼整潔之道》

        https://github.com/ryanmcdermott/clean-code-javascript

        https://github.com/ryanmcdermott/3rs-of-software-architecture

        https://alexkondov.com/tao-of-react/

        參考資料

        [1]

        Alex Kondov: https://twitter.com/alexanderkondov

        [2]

        tao-of-react: https://alexkondov.com/tao-of-react/

        [3]

        readable, reusable, and refactorable: https://github.com/ryanmcdermott/3rs-of-software-architecture

        瀏覽 57
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            91丨豆花丨国产熟女 | 国产女主播AV在线 | 安娜大尺度做爰未删减视频 | 色色色色色综合 | 揉捏穆桂英双乳三级潘金莲 | 黄大色黄女片18免费 | 国产精品igao视频网网址男男 | 91麻豆精品国产91久久久吃药 | 国产艹艹逼| 婷婷深爱网|