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

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

毒舌时刻

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

你以为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)搭配本地千问模型(零token成本)实现电脑AI助理

龙虾(OpenClaw)搭配本地千问模型(零token成本)实现电脑AI助理

前言:现在AI助手遍地都是,但要么是云端服务要花token钱,要么是功能单一只能聊天,想找一个“不花钱、能干活、保隐私”的电脑AI助理,简直比登天!直到我发现了一个神仙组合——龙虾AI(OpenClaw)+ 本地千问模型,完美解决所有痛点:零token成本、全程本地运行、能接管电脑干活,无论是办公摸鱼还是高效产出,都能轻松拿捏。 本文是纯新手向原创实操教程,全程手把手,从工具认知、环境准备,到龙虾与本地千问的联动配置,再到实战场景演示,每一步都标清重点、避开坑点,不用懂复杂代码,不用花一分钱,普通人跟着走,10分钟就能拥有专属本地AI电脑助理,从此告别云端token焦虑和隐私泄露风险! 一、先搞懂:为什么是“龙虾+本地千问”?核心优势碾压同类组合 在开始操作前,先跟大家说清楚两个核心工具的作用,以及为什么它们搭配起来是“王炸”——毕竟市面上AI工具那么多,选对组合才能少走弯路,真正实现“零成本、高效率”。 1. 两个核心工具,

AI提示词:零基础入门与核心概念

AI提示词:零基础入门与核心概念

AI提示词:零基础入门与核心概念 📝 本章学习目标:理解什么是提示词,掌握提示词的核心概念,建立正确的AI对话思维,为后续学习打下坚实基础。 一、什么是提示词? 1.1 提示词的定义 提示词(Prompt),简单来说,就是你发给AI的指令或问题。它是人类与人工智能沟通的桥梁,是你告诉AI"我想要什么"的方式。 想象一下,你雇佣了一位超级聪明但对你的需求一无所知的助手。这位助手知识渊博、能力强大,但它需要你清晰地告诉它要做什么。提示词就是你给这位助手的工作指令。 💡 核心认知:提示词不是简单的"提问",而是一种结构化的指令设计。好的提示词能让AI精准理解你的意图,输出高质量的结果;糟糕的提示词则会让AI"答非所问",浪费你的时间。 1.2 提示词的重要性 为什么提示词如此重要?让我们通过一个对比来说明: ❌ 糟糕的提示词: 帮我写点东西 ✅ 好的提示词: 请帮我写一篇关于&

AI 大模型落地系列|Eino ADK体系篇:你对 ChatModelAgent 有了解吗?

AI 大模型落地系列|Eino ADK体系篇:你对 ChatModelAgent 有了解吗?

声明:本文源于官方文档,重点参考 Eino ADK: ChatModelAgent、Eino ADK: 概述、Eino ADK: Agent 协作 分享一个很棒的AI技术博客,对AI感兴趣的朋友强烈推荐去看看http://blog.ZEEKLOG.net/jiangjunshow。 为什么很多人把 ChatModelAgent 想简单了?一文讲透 ReAct、Transfer、AgentAsTool 与 Middleware * 1. 为什么很多人会把 `ChatModelAgent` 想简单 * 2. `ChatModelAgent` 在 ADK 里到底是什么 * 3. 其内部本质是一个 `ReAct` 循环 * 没有 Tool 时会怎样 * 为什么还需要 `MaxIterations` * 4. 哪几组配置真正决定了行为 * `Name / Description`