为什么作一名 in-house程序员很糟糕?

本文探讨了在非软件企业工作的程序员所面临的挑战,包括工作方式受限、产品改进空间小、职业发展受限等问题。在这样的环境中,程序员难以成为业界高手,并且很难提升自己的技能和地位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按:节选自Joel Spolsky的《More Joel on Software》。这里in-house programmer是指在非软件企业工作的程序员。

我的理解是,软件开发是很复杂的领域,有其专有的方法论和组织文化,专门从事软件的企业比较容易拥有这些关键元素。但非软件企业的企业文化往往并不太适合打造软件,管理层也不太懂软件开发方面的知识,不晓得软件工程到底是什么,以为把几个程序员招来凑到一起就能做出所谓的软件来(这也许就是《浪潮之巅》中提到的企业基因吧)。所以在这种环境下,作一名in-house programmer会比较难成为业界高手,同时由于软件不是公司的核心业务,所以也不太可能得到很多升迁机会。

 

OK, so, why does it suck to be an in-house programmer?

Number one: you never get to do things theright way. You always have to do things the expedient way.

The second reason these jobs suck: as soon as your program gets good enough, you have to stop working on it. Once the core functionality is there, the main problem is solved; there is absolutely no return on investment, no business reason to make the software any better. So all of these in-house programs look like a dog’s breakfast: because it’s just not worth a penny to make them look nice. Forget any pride in workmanship or craftsmanship you learned in CS 323. You’re going to churn out embarrassing junk,and then, you’re going to rush off to patch up last year’s embarrassing junk,which is starting to break down because it wasn’t done right in the first place, twenty-seven years of that and you get a gold watch. Oh, and they don’tgive gold watches any more. Twenty-seven years and you get carpal tunnel syndrome. Now, at a product company, for example, if you’re a software developer working on a software product or even an online product like Google or Facebook, the better you make the product, the better it sells. The key pointabout in-house development is that once it’s “good enough,” you stop. When you’re working on products, you can keep refining and polishing and refactoring and improving, and if you work for Facebook, you can spend a whole month optimizingthe Ajax name-choosing gizmo so that it’s really fast and really cool, and allthat effort is worthwhile because it makes your product better than the competition. So, the number two reason product work is better than in-house work is that you get to make beautiful things.

 

Number three: when you’re a programmer at a software company, the work you’re doing is directly related to the way the company makes money. That means, for one thing, that management cares aboutyou. It means you get the best benefits and the nicest offices and the best chances for promotion. A programmer is never going to rise to become CEO of Viacom, but you might well rise to become CEO of a tech company.

 

Access to XMLHttpRequest at 'http://localhost:1030/zuke/house/list' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.了解此错误 HouseList.vue:74 POST http://localhost:1030/zuke/house/list net::ERR_FAILED 200 (OK) dispatchXhrRequest @ axios.js?v=58a38777:1648 xhr @ axios.js?v=58a38777:1528 dispatchRequest @ axios.js?v=58a38777:2003 _request @ axios.js?v=58a38777:2224 request @ axios.js?v=58a38777:2115 httpMethod @ axios.js?v=58a38777:2253 wrap @ axios.js?v=58a38777:8 loadData @ HouseList.vue:74 setup @ HouseList.vue:51 callWithErrorHandling @ chunk-UQWBJQZ5.js?v=58a38777:2263 setupStatefulComponent @ chunk-UQWBJQZ5.js?v=58a38777:9983 setupComponent @ chunk-UQWBJQZ5.js?v=58a38777:9944 mountComponent @ chunk-UQWBJQZ5.js?v=58a38777:7300 processComponent @ chunk-UQWBJQZ5.js?v=58a38777:7266 patch @ chunk-UQWBJQZ5.js?v=58a38777:6782 componentUpdateFn @ chunk-UQWBJQZ5.js?v=58a38777:7490 run @ chunk-UQWBJQZ5.js?v=58a38777:481 runIfDirty @ chunk-UQWBJQZ5.js?v=58a38777:519 callWithErrorHandling @ chunk-UQWBJQZ5.js?v=58a38777:2263 flushJobs @ chunk-UQWBJQZ5.js?v=58a38777:2471 Promise.then queueFlush @ chunk-UQWBJQZ5.js?v=58a38777:2385 queueJob @ chunk-UQWBJQZ5.js?v=58a38777:2380 effect2.scheduler @ chunk-UQWBJQZ5.js?v=58a38777:7532 trigger @ chunk-UQWBJQZ5.js?v=58a38777:509 endBatch @ chunk-UQWBJQZ5.js?v=58a38777:567 notify @ chunk-UQWBJQZ5.js?v=58a38777:827 trigger @ chunk-UQWBJQZ5.js?v=58a38777:801 set value @ chunk-UQWBJQZ5.js?v=58a38777:1673 finalizeNavigation @ vue-router.js?v=58a38777:2672 (匿名) @ vue-router.js?v=58a38777:2582 Promise.then pushWithRedirect @ vue-router.js?v=58a38777:2550 push @ vue-router.js?v=58a38777:2476 install @ vue-router.js?v=58a38777:2831 use @ chunk-UQWBJQZ5.js?v=58a38777:5940 (匿名) @ main.js:16了解此错误 Sidebar.vue:59 {data: {…}, status: 200, statusText: '', headers: AxiosHeaders, config: {…}, …}config: {transitional: {…},
最新发布
06-04
<think>嗯,用户遇到了Vue.js项目中通过axios发送请求时出现的CORS策略拦截问题,核心诉求很明确:"解决CORSpolicyerrorAccess-Control-Allow-OriginVue.jsaxioslocalhost"。从引用内容看,用户应该是在本地开发环境(localhost:8081前端调用localhost:8080后端)遇到了两种典型错误:一种是缺失响应头,另一种是凭据模式与通配符冲突。用户可能正在调试登录接口(引用2提到/userLogin)或资源创建接口(引用3提到/pod/create),这些通常涉及敏感操,所以浏览器安全策略特别严格。ta显然已经查阅过部分资料,但被技术细节绕晕了。情绪上应该比较烦躁,毕竟跨域问题会直接阻塞开发进度。深层需求其实是"快速让项目跑起来",而不仅是理解CORS原理。不过为专业支持,既要给应急方案(如代理配置),也要给根治方案(服务端配置)。需要重点提醒几个易错点:1)withCredentials和通配符*的互斥性,这点在引用2已明确提示2)预检请求(preflight)的特殊处理,很多开发者会忽略OPTIONS方法的配置3)生产环境部署时的差异(比如Nginx和本地代理配置不同)比较意外的是用户没提具体技术栈(如SpringBoot或Express),但引用提到8080端口,大概率是Java系后端。解决方案设计要分层:-短期方案:优先推荐devServer代理,因为前端能独立操-中期方案:指导后端添加CORS头,解决根本问题-特殊场景:需传递cookie时的安全配置需要明确避开两个坑:1)chrome禁用安全策略之类的方案,既不安全也不可持续2)后端返回Access-Control-Allow-Origin:*但前端又设withCredentials=true的矛盾组合最后要注意用户可能是全栈新手,所以proxy配置示例必须完整包含pathRewrite和changeOrigin这类关键参数,避免二次踩坑。</think> 好的,针对您在Vue.js项目中使用Axios向localhost后端发送请求时遇到的CORS策略错误(`Access-Control-Allow-Origin`),以下是一步步的解决方案,综合了引用中的关键信息和最佳实践: **核心问题:** 浏览器同源策略阻止了您运行在 `http://localhost:8081` 的前端Vue应用直接访问运行在 `http://localhost:8080` 的后端API,即使它们都在同一台机器上,**端口不同即视为不同源**。浏览器要求后端在响应中包含特定的CORS头部(主要是`Access-Control-Allow-Origin`)明确授权前端来源。 **常见错误信息及含义:** 1. **`No 'Access-Control-Allow-Origin' header is present on the requested resource` ([^1], [^3]):** * **含义:** 后端服务器**完全没有返回**必需的`Access-Control-Allow-Origin`响应头。 * **根本原因:** 后端未配置处理CORS请求。 2. **`The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*' when ... credentials mode is 'include'` ([^2]):** * **含义:** 后端设置了`Access-Control-Allow-Origin: *`(允许所有源),但您的前端Axios请求设置了`withCredentials: true`(需携带凭据如cookies)。 * **根本原因:** 浏览器安全策略不允许在发送凭据的情况下使用通配符`*`。后端需要明确指定允许的前端来源(即`http://localhost:8081`),且需设置`Access-Control-Allow-Credentials: true`。 --- **解决方案:(分优先级推荐)** **最优方案:后端配置CORS (强烈推荐,一劳永逸)** * **原因:** CORS是服务端行为,根治方法是让后端正确配置CORS响应头。 * **步骤(取决于后端框架):** 1. **识别来源:** 确定您的Vue前端应用的访问地址(通常是 `http://localhost:8081`,Vite可能是 `http://localhost:5173`)。 2. **配置后端:** * **通用方法 (Java Servlet Filter, Node.js middleware 等):** * 检查 `Origin` 请求头。 * 如果 `Origin` 在白名单内(如`http://localhost:8081`),则在响应中添加: * `Access-Control-Allow-Origin: http://localhost:8081` (精确匹配) 或配置允许的列表。 * 如果前端需要发送凭据(cookies),**必须**: * 设置 `Access-Control-Allow-Credentials: true`。 * 并且 `Access-Control-Allow-Origin` **不能为** `*`,必须是指定前端源(如`http://localhost:8081`)。 * `Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS` (允许的方法)。 * `Access-Control-Allow-Headers: Content-Type, Authorization, ...` (允许的请求头)。 * 对于 `OPTIONS` 方法的请求(预检请求),应直接返回 `200 OK` 并包含上述头部。 * **框架特定(常见示例):** * **Spring Boot (Java):** 使用 `@CrossOrigin` 注解(单个控制器或方法)或配置全局 `WebMvcConfigurer` Bean。 ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 对所有API路径 .allowedOrigins("http://localhost:8081", "http://localhost:5173") // 允许的源 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); // 允许凭据 } } ``` * **Express (Node.js):** 使用 `cors` 中间件。 ```javascript const express = require('express'); const cors = require('cors'); const app = express(); const corsOptions = { origin: ['http://localhost:8081', 'http://localhost:5173'], // 允许的源数组 credentials: true, // 允许凭据 }; app.use(cors(corsOptions)); // 应用中间件 ``` * **Flask (Python):** 使用 `flask_cors` 扩展。 ```python from flask import Flask from flask_cors import CORS app = Flask(__name__) cors = CORS(app, resources={r"/api/*": {"origins": ["http://localhost:8081", "http://localhost:5173"]}}, supports_credentials=True) ``` * **优点:** 解决最彻底,符合标准,适用于开发和最终上线环境。解决了引用[^1]、[^2]、[^3]中的所有核心问题。 * **缺点:** 需要修改后端代码和可能的权限(如果您不负责后端)。 **次优方案(开发期):Vue开发服务器代理 (Proxy)** * **原因:** 利用Vue CLI或Vite的开发服务器为中间代理,将API请求转发到后端服务器。浏览器只看到同源(对Vue开发服务器的请求),解决了CORS问题。 * **步骤 (Vue CLI / Vite 通用原理):** 1. **配置 `vite.config.js` (Vite) 或 `vue.config.js` (Vue CLI):** ```javascript // vite.config.js 或 vue.config.js export default defineConfig({ server: { proxy: { '/api': { // 设置代理路径前缀,可以是任意字符串 '/myapi' 等 target: 'http://localhost:8080', // 后端目标地址 changeOrigin: true, // 关键!修改请求头中的 Origin 为 target rewrite: (path) => path.replace(/^\/api/, '') // (可选) 重写路径,去掉代理前缀 }, // 可以代理多个路径 '/another-api': { target: 'http://localhost:8081', changeOrigin: true, } } } }) ``` 2. **修改Axios `baseURL` (推荐):** 在创建Axios实例的地方,设置 `baseURL` 为代理前缀 `/api`(或其他你设置的前缀)。 ```javascript // 例如在 src/api/index.js 或 main.js import axios from 'axios'; const api = axios.create({ baseURL: '/api', // 指向代理配置的前缀 // withCredentials: true, // 如果后端需要认证,取消注释,并确保后端配置支持凭据(见方案一) }); export default api; ``` 3. **重启开发服务器:** `npm run dev` / `vite`。 4. **发起请求:** 在Vue组件中,像这样调用API:`api.get('/users')`。浏览器会发请求到 `http://localhost:5173/api/users` (Vite),开发服务器将其代理到 `http://localhost:8080/users`。 * **优点:** * 完全规避前端CORS问题(浏览器只访问同源的开发服务器)。 * 不需要更改后端代码。 * 开发环境快速配置。 * **缺点:** * 仅适用于**开发环境**。部署上线时不能这样解决(部署后需要真正的前后端同源或后端正确配置CORS)。 * 不会触发预检请求 (`OPTIONS`),可能掩盖一些潜在的服务器问题(如某些不支持的动词或自定义头部问题)。 * 需要在Axios请求中使用代理路径前缀。 **关于 `withCredentials` 的建议:** * 只有当您的请求**需要发送/接收Cookies、HTTP认证信息等用户凭据**时,才需要在Axios设置 `withCredentials: true`。 * 一旦设置了 `withCredentials: true`,后端响应**必须**: * 设置 `Access-Control-Allow-Origin` 为**精确的前端源**(不能是`*`)。 * 设置 `Access-Control-Allow-Credentials: true`。 * 否则会遇到引用[^2]中的错误。 * 在大多数登录认证(如使用Session Cookie)的场景下,这个设置是必要的。 **总结步骤 (推荐顺序):** 1. **首选:尝试配置后端CORS。** * 确定Vue前端访问地址。 * 让后端精确配置 `Access-Control-Allow-Origin` 为该地址。 * 如果前端设置 `withCredentials: true`,后端**必须同时精确设置允许来源**并设置 `Access-Control-Allow-Credentials: true`。 2. **开发期快速方案(如果后端暂时无法修改):配置Vue开发服务器代理 (`proxy`)。** * 修改 `vite.config.js`/`vue.config.js`。 * 设置Axios的 `baseURL` 指向代理前缀。 * 记住这是开发环境的临时方案。 3. **检查 `withCredentials` 设置:** 根据需求(是否传递凭据)决定是否在Axios中设置 `withCredentials: true`,如果设置了,确保后端配置与之匹配(非 `*` + `Allow-Credentials: true`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值