前端代码质量保证:让你的代码更可靠

前端代码质量保证:让你的代码更可靠

毒舌时刻

代码质量?听起来就像是前端工程师为了显得自己很专业而特意搞的一套复杂流程。你以为随便写几个测试就能保证代码质量?别做梦了!到时候你会发现,测试代码比业务代码还多,维护起来比业务代码还麻烦。

你以为ESLint能解决所有问题?别天真了!ESLint只能检查代码风格,无法检查逻辑错误。还有那些所谓的代码质量工具,看起来高大上,用起来却各种问题。

为什么你需要这个

  1. 减少错误:代码质量保证可以帮助你发现和修复代码中的错误,减少生产环境中的问题。
  2. 提高可维护性:高质量的代码更容易理解和维护,减少后期的维护成本。
  3. 促进团队协作:统一的代码质量标准可以便于团队成员之间的协作,减少沟通成本。
  4. 提高开发效率:高质量的代码可以减少调试和修复错误的时间,提高开发效率。
  5. 提升代码安全性:代码质量保证可以帮助你发现和修复安全漏洞,提升代码的安全性。

反面教材

// 这是一个典型的代码质量问题示例 // 1. 代码风格不一致 function getUser(id) { return fetch(`/api/users/${id}`) .then(res => res.json()) .then(data => { return data; }); } function getProduct(id){ return fetch(`/api/products/${id}`).then(res=>res.json()).then(data=>data); } // 2. 未使用的变量 function calculateTotal(price, quantity) { const tax = 0.08; const discount = 0.1; return price * quantity; } // 3. 硬编码值 function getShippingCost(weight) { if (weight < 10) { return 5.99; } else if (weight < 20) { return 9.99; } else { return 14.99; } } // 4. 缺少错误处理 function fetchData() { fetch('/api/data') .then(response => response.json()) .then(data => console.log(data)); } // 5. 复杂的条件语句 function getDiscount(user, product) { if (user.isMember && user.membershipLevel >= 3) { if (product.category === 'electronics') { return 0.2; } else if (product.category === 'clothing') { return 0.15; } else { return 0.1; } } else if (user.isMember) { if (product.category === 'electronics') { return 0.1; } else if (product.category === 'clothing') { return 0.08; } else { return 0.05; } } else { return 0; } } 

问题

  • 代码风格不一致,影响可读性
  • 未使用的变量,增加代码复杂度
  • 硬编码值,难以维护
  • 缺少错误处理,容易导致应用崩溃
  • 复杂的条件语句,难以理解和维护

正确的做法

代码风格规范

// 1. ESLint配置 // .eslintrc.js module.exports = { env: { browser: true, es2021: true, node: true }, extends: [ 'eslint:recommended', 'plugin:react/recommended', 'plugin:react-hooks/recommended' ], parserOptions: { ecmaFeatures: { jsx: true }, ecmaVersion: 12, sourceType: 'module' }, plugins: [ 'react', 'react-hooks' ], rules: { 'react/prop-types': 'off', 'react/react-in-jsx-scope': 'off', 'indent': ['error', 2], 'linebreak-style': ['error', 'unix'], 'quotes': ['error', 'single'], 'semi': ['error', 'always'], 'no-unused-vars': 'error', 'no-console': 'warn' } }; // 2. Prettier配置 // .prettierrc.js module.exports = { semi: true, trailingComma: 'es5', singleQuote: true, printWidth: 80, tabWidth: 2 }; // 3. EditorConfig配置 // .editorconfig root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false 

代码质量工具

// 1. ESLint // 安装 npm install --save-dev eslint eslint-plugin-react eslint-plugin-react-hooks // 配置脚本 { "scripts": { "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0" } } // 2. Prettier // 安装 npm install --save-dev prettier // 配置脚本 { "scripts": { "format": "prettier --write ." } } // 3. Stylelint // 安装 npm install --save-dev stylelint stylelint-config-standard // 配置 // .stylelintrc.js module.exports = { extends: 'stylelint-config-standard', rules: { 'indentation': 2, 'string-quotes': 'single' } }; // 配置脚本 { "scripts": { "lint:css": "stylelint '**/*.css'" } } // 4. TypeScript // 安装 npm install --save-dev typescript @types/react @types/react-dom // 配置 // tsconfig.json { "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": ["src"] } // 配置脚本 { "scripts": { "typecheck": "tsc --noEmit" } } 

测试工具

// 1. Jest // 安装 npm install --save-dev jest @testing-library/react @testing-library/jest-dom // 配置 // jest.config.js module.exports = { testEnvironment: 'jsdom', transform: { '^.+\\.(js|jsx)$': 'babel-jest' }, moduleNameMapper: { '\\.(css|less|scss|sass)$': 'identity-obj-proxy' }, setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'] }; // 配置脚本 { "scripts": { "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage" } } // 2. React Testing Library // 测试示例 import { render, screen, fireEvent } from '@testing-library/react'; import App from './App'; test('renders learn react link', () => { render(<App />); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); }); test('increments counter when button is clicked', () => { render(<App />); const buttonElement = screen.getByText(/increment/i); const counterElement = screen.getByText(/count:/i); fireEvent.click(buttonElement); expect(counterElement).toHaveTextContent('Count: 1'); }); // 3. Playwright (E2E测试) // 安装 npm install --save-dev @playwright/test // 配置 // playwright.config.js module.exports = { use: { baseURL: 'http://localhost:3000', headless: true, viewport: { width: 1280, height: 720 }, ignoreHTTPSErrors: true } }; // 测试示例 // tests/example.spec.js const { test, expect } = require('@playwright/test'); test('has title', async ({ page }) => { await page.goto('/'); await expect(page).toHaveTitle(/React App/); }); test('get started link', async ({ page }) => { await page.goto('/'); await page.click('text=Learn React'); await expect(page).toHaveURL(/.*react.dev/); }); // 配置脚本 { "scripts": { "test:e2e": "playwright test" } } 

代码审查

// 1. GitHub Actions配置 // .github/workflows/code-quality.yml name: Code Quality on: push: branches: [ main ] pull_request: branches: [ main ] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Node.js uses: actions/setup-node@v2 with: node-version: '16' - name: Install dependencies run: npm install - name: Run ESLint run: npm run lint - name: Run Prettier run: npm run format -- --check - name: Run TypeScript run: npm run typecheck - name: Run tests run: npm test // 2. 代码审查工具 // 安装 npm install --save-dev eslint-plugin-security eslint-plugin-sonarjs // 配置 // .eslintrc.js module.exports = { plugins: [ 'security', 'sonarjs' ], rules: { 'security/detect-unsafe-regex': 'error', 'security/detect-buffer-noassert': 'error', 'sonarjs/cognitive-complexity': ['error', 15], 'sonarjs/no-duplicate-string': ['error', { threshold: 3 }] } }; 

最佳实践

// 1. 代码组织 // 按功能组织文件 /src /components /Button Button.jsx Button.css Button.test.jsx /Card Card.jsx Card.css Card.test.jsx /pages /Home Home.jsx Home.css Home.test.jsx /About About.jsx About.css About.test.jsx /utils api.js helpers.js constants.js /hooks useAuth.js useLocalStorage.js /context AuthContext.jsx ThemeContext.jsx // 2. 命名规范 // 组件名:PascalCase function UserProfile() { return <div>User Profile</div>; } // 变量名:camelCase const userCount = 10; // 常量:UPPER_SNAKE_CASE const API_BASE_URL = 'https://api.example.com'; // 函数名:camelCase function getUserData() { return fetch('/api/user'); } // 3. 错误处理 async function fetchData() { try { const response = await fetch('/api/data'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('Error fetching data:', error); throw error; } } // 4. 注释 /** * 获取用户信息 * @param {number} id - 用户ID * @returns {Promise<Object>} 用户信息 */ async function getUser(id) { const response = await fetch(`/api/users/${id}`); return response.json(); } // 5. 模块化 // utils/api.js export async function fetchUsers() { const response = await fetch('/api/users'); return response.json(); } export async function fetchProducts() { const response = await fetch('/api/products'); return response.json(); } // 使用 import { fetchUsers, fetchProducts } from './utils/api'; async function loadData() { const [users, products] = await Promise.all([ fetchUsers(), fetchProducts() ]); return { users, products }; } 

毒舌点评

代码质量保证确实很重要,但我见过太多开发者滥用这个特性,导致开发流程变得过于复杂。

想象一下,当你为了通过代码审查,写了大量的测试代码和注释,结果导致代码量增加了几倍,这真的值得吗?

还有那些过度使用代码质量工具的开发者,为了满足工具的要求,写了大量的冗余代码,结果导致代码变得难以理解和维护。

所以,在进行代码质量保证时,一定要把握好度。不要为了追求代码质量而牺牲开发效率,要根据实际情况来决定代码质量保证的策略。

当然,对于大型项目来说,代码质量保证是必不可少的。但对于小型项目,过度的代码质量保证反而会增加开发成本和维护难度。

最后,记住一句话:代码质量保证的目的是为了提高代码的可靠性和可维护性,而不是为了炫技。如果你的代码质量保证策略导致开发变得更慢或更复杂,那你就失败了。

Read more

深入解析OpenClaw Skills:从原理到实战,打造专属机器人技能

深入解析OpenClaw Skills:从原理到实战,打造专属机器人技能

一、OpenClaw Skills:机器人行为的“最小执行单元” 1.1 什么是OpenClaw Skills? OpenClaw是面向开源机械爪/小型机器人的控制框架(核心仓库:openclaw/openclaw),旨在降低机器人行为开发的门槛。而Skills(技能) 是OpenClaw框架中对机器人“单一可执行行为”的封装模块——它将机器人完成某一特定动作的逻辑(如“夹取物体”“释放物体”“移动到指定坐标”)抽象为独立、可复用、可组合的代码单元。 简单来说: * 粒度:一个Skill对应一个“原子行为”(如“单指闭合”)或“组合行为”(如“夹取→移动→释放”); * 特性:跨硬件兼容(适配不同型号机械爪)、可插拔(直接集成到OpenClaw主框架)、可扩展(支持自定义参数); * 核心价值:避免重复开发,让开发者聚焦“

【Axure教程】AI自动对话机器人

【Axure教程】AI自动对话机器人

AI对话机器人的应用已经非常广泛,从你日常使用的手机助手到企业复杂的客服系统,背后都有它的身影。所以今天就教大家在Axure里制作Ai对话机器人的原型模版,制作完成后,只需要在中继器表格里输入问题和答案,预览时就可以实现自动回复。具体效果你们可以观看下面的视频或打开原型预览地址亲自体验 【原型效果】 1、在输入框里输入问题后,自动搜索问题列表,如果找到答案,机器人自动回复;如果找不到答案,也会回复引导话术。 2、机器人回复时,会模拟打字输入效果,逐字回复。 3、问题和答案,可以在中继器表格里添加或修改。 【原型预览含下载地址】 https://axhub.im/ax10/bcf9d9e5357143b7/#c=1 【制作教程】 本原型模版主要分成底部背景、欢迎区域、问题列表、对话区域输入区域 1.底部背景 底部背景用矩形和线段制作,如下图所示摆放 2.欢迎区域 欢迎区域包括图标和文字,默认未提问时显示。 3.问题列表 问题列表用中继器制作,中继器里摆放矩形和文本标签,矩形用于显示文字,文本标签用于记录答案,

【Mac 实战】简单知识图谱搭建步骤详解(Neo4j + py2neo)

【Mac 实战】简单知识图谱搭建步骤详解(Neo4j + py2neo)

目录 一、Neo4j图数据库 1、neo4j 安装 - mac brew版 2、neo4j 快速入门 3、neo4j 基本操作 (1)增操作 (2)查操作 (3)改操作 (4)删操作 4、安装py2neo 二、数据预处理 1、数据清洗 2、知识建模 (1)识别实体 (2)识别实体属性 (3)识别关系 三、搭建知识图谱 博主的数据集是用的自己的数据集,大家练习时可以在网上找一个数据量小的数据集练手。 一、Neo4j图数据库         Neo4j 是一个高性能的、原生的图数据库。它不采用传统的行和列的表格结构,而是使用节点和关系的图结构来存储和管理数据。 1、neo4j

从人类视频到机器人跳舞:BeyondMimic 全流程解析与 rl_sar 部署实践

从人类视频到机器人跳舞:BeyondMimic 全流程解析与 rl_sar 部署实践

0. 前言 让人形机器人学会跳舞,听起来像是科幻电影中的场景,但在强化学习和运动模仿技术的推动下,这件事正在变得越来越现实。本文将完整介绍一条从"人类 RGB 视频"到"真实机器人跳舞"的技术链路:首先通过视觉算法从视频中提取人体运动轨迹,然后将人体模型重定向到机器人关节空间,接着在仿真环境中进行强化学习训练,最后在 MuJoCo 中验证并部署到真实的 Unitree G1 人形机器人上。 整条流程涉及四个核心开源项目:GVHMR(视频到人体模型)、GMR(人体到机器人重定向)、BeyondMimic(强化学习训练框架)、以及 rl_sar(仿真验证与真机部署框架)。本文不仅会逐一拆解每个环节的原理和操作步骤,还会深入分析 BeyondMimic 的算法设计,并详细记录将训练产物迁移到 rl_sar 项目中进行 sim2sim 和 sim2real 部署时遇到的关键问题与解决方案。 下图展示了