注册
环信即时通讯云

环信即时通讯云

单聊、群聊、聊天室...
环信开发文档

环信开发文档

Demo体验

Demo体验

场景Demo,开箱即用
RTE开发者社区

RTE开发者社区

汇聚音视频领域技术干货,分享行业资讯
技术讨论区

技术讨论区

技术交流、答疑
资源下载

资源下载

收集了海量宝藏开发资源
iOS Library

iOS Library

不需要辛辛苦苦的去找轮子, 这里都有
Android Library

Android Library

不需要辛辛苦苦的去找轮子, 这里都有

人类一生所学不过 4GB,加州理工顶刊新研究引热议

24 小时不间断学习且不遗忘,一辈子也只有 4GB 的 “知识储量”? 科学家们最新研究,计算出了人类学习积累上限,就这么多~~(甚至还不如一块 U 盘能装)。 这是来自 Cell 旗下神经科学顶刊 Neuron 上的一项工作,它提出了一个发人深省的悖论: ...
继续阅读 »

24 小时不间断学习且不遗忘,一辈子也只有 4GB 的 “知识储量”?


科学家们最新研究,计算出了人类学习积累上限,就这么多~~(甚至还不如一块 U 盘能装)。



这是来自 Cell 旗下神经科学顶刊 Neuron 上的一项工作,它提出了一个发人深省的悖论:



人类信息处理速度仅为每秒 10bit,而我们的感官系统却能以每秒 10 亿 bit 的速率收集数据。




由此,按照每秒 10bit 的速度来算,人类 24 小时不间断学习且不遗忘,100 年储存的知识也不过 4GB。


什么概念呢?来和大模型做个对比:


大语言模型每个参数就能存储 2bit 知识,一个 70 亿参数的模型就能存储 140 亿 bit 的知识。



结论来自华人学者朱泽园”Physics of Language Models” 系列论文

难怪研究人员还提出了一项推论:



随着算力的不断提升,机器在各类任务中的表现超越人类只是时间问题。



另外,按照这项研究的结论,马斯克目前的脑机接口研究也有问题了。


研究人员表示:



我们预测马斯克的大脑与计算机的通信速率大约为 10bit/s。与其使用 Neuralink 的电极束,不如直接使用电话,因为电话的数据传输率已经被设计得与人类语言相匹配,而人类语言又与感知和认知的速度相匹配。




一时间,这一系列惊人推论在学术圈各大社区引起广泛讨论。


美国知名医师科学家、斯克里普斯转化研究所创始人 Eric Topol 也忍不住下场转发。



为啥我们一次只能思考一件事呢?




所以,结论如何得出的?


中枢神经系统 “串行” 影响信息处理速率


简单说,要想计算人一辈子能学多少知识,我们得先从大脑处理信息的速度说起。


从对几项日常活动(如打字、说话演讲、拧魔方等)的评估来看,他们初步得出 “大脑处理信息的速度约为 10bits/s” 这一结论。


以人类打字为例,高级打字员每分钟能打 120 个单词(每秒 2 个),平均每个单词按 5bit 计算,那么信息传输速率就是 10bits/s。



同样,若以英语演讲为例,如果将节奏控制在舒适程度——讲话速度为每分钟 160 个单词,则信息传输速率为 13bits/s,略高于打字。


再比如 “盲拧魔方” 这项竞技活动,选手需先观察魔方几秒,然后闭眼还原。以一次世界纪录的成绩 12.78s 为例,其中观察阶段约 5.5s,由于魔方可能的排列数约为 4.3x1016≈265,则最终信息传输速率约为 11.8bits/s


使用类似方式,作者估算了更多场景下的信息处理速度(从经典实验室实验到现代电子竞技等),结果显示为 5~50bits/s 之间。



由此也得出一个整体结论:人类思考的速度始终在 10bits/s 的尺度范围内


按照这一标准,假设我们能活 100 岁,每天 24 小时不间断学习(且剔除遗忘因素),那么我们最终的 “知识储量” 也将不到 4GB。



事实上,与 10bits/s 形成鲜明对照的是——人类感官系统以约 10 亿 bits/s 的速率收集数据。



10bits/s VS 10 亿 bits/s



具体来说,我们每天从周围环境中获取信息的速率就以 Gbps/s 起算。


举个栗子,视觉系统中单个视锥细胞能以 270bits/s 的速度传输信息,而一只眼睛就拥有约 600 万个视锥细胞。


那么,光是双眼视觉系统接收信息的速度就高达 3.2Gbps/s。照此推算,我们接收信息的速度与处理信息的速度之间的差距比值竟然达到了 108:1。



要知道,人类大脑里有超过 850 亿个神经元,其中三分之一集中在大脑皮层组成了复杂的神经网络。也就是说,明明单个神经元就能轻松处理超过 10bits/s 的信息。


而现在所观察到的现象却与之不符,显而易见,上述二者之间存在一定矛盾



从神经元本身的性能来看,它们具备快速处理和传输信息的能力,但这并没有直接转化为整体认知速度的提升,说明还有其他因素在起作用。



那么,为什么人类信息处理速度如此之慢?



按照论文分析,原因可能在以下几个方面:


最主要的,中枢神经系统在处理信息时采用的是串行方式,对信息传输速率有所限制。


这里要提到并行处理和串行处理之间的区别。


所谓并行处理,显然指多个任务同时进行。以我们看东西为例,视网膜每秒会产生 100 万个输出信号,每一个信号都是视网膜神经元对视觉图像局部计算的结果,由此同时处理大量视觉信息。


而在中枢神经系统中,他们观察到了一种 “心理不应期”(psychological refractory period)效应,即同时面对多个任务,中枢神经系统只将注意力集中在一个任务上。


当然,他们也进一步探究了出现 “串行” 背后的原因,结论是这与演化过程早期的神经系统功能有关


展开来说,那些最早拥有神经系统的生物,核心利用大脑来检测气味分子的浓度梯度,以此判断运动方向进行捕食和避开敌人。长此以往,这种特定功能需求使得大脑逐渐形成了 “一次处理一个任务” 的认知架构。



在进化过程中,大脑的这种架构逐渐固化,虽然随着物种的进化,大脑的功能越来越复杂,但这种早期形成的认知架构仍然在一定程度上限制了我们同时处理多个任务和快速处理信息的能力。



除此之外,还有理论认为存在 “注意瓶颈” 等限制了信息处理。注意力是认知过程中的一个重要因素,它就像一个瓶颈,限制了能够进入认知加工阶段的信息数量和速度,不过其具体运作机制目前人类尚未完全理解。


总之,按照论文的观点,10bits/s 这样的速度已经可以满足人类生存需求,之所以还存在庞大的神经元网络,原因可能是我们需要频繁切换任务,并整合不同神经回路之间的信息。


马斯克脑机接口过于理想化


不过话虽如此,鉴于 10bits/s 和 10 亿 bits/s 之间的巨大差距,人类越来越无法忍受慢节奏了。


由此论文也得出一个推断:随着算力的不断提升,机器在各类任务中的表现超越人类只是时间问题。


换成今天的话说,以 AI 为代表的新物种将大概率逐渐 “淘汰” 人类。


另外,论文还顺带调侃了马斯克的脑机接口系统。


其中提到,马斯克的行动基于肉体带宽不足对处理信息的限制。按照老马的设想,一旦通过高带宽接口直接连接人脑和计算机,人类就可以更自由地和 AI 交流,甚至共生。



然而他们认为这一想法有些过于理想化。



10bits/s 的限制源于大脑基本结构,一般无法通过外部设备来突破。



由此也提出开头提到的建议:



与其使用 Neuralink 的电极束,不如直接使用电话,因为电话的数据传输率已经被设计得与人类语言相匹配,而人类语言又与感知和认知的速度相匹配。



不过上述言论也并非意味着他们对脑机接口失去信心,他们认为其关键并不在于突破信息速率限制,而是以另一种方式提供和解码患者所需信息。


作者之一为上海交大校友


这项研究由来自加州理工学院生物学与生物工程系的两位学者完成。



Jieyu Zheng 目前是加州理工学院五年级博士研究生,她还是上海交大本科校友,还有康奈尔大学生物工程学士学位,在剑桥大学获得教育与心理学硕士学位。


她的研究重点聚焦于认知灵活性、学习和记忆,特别关注大脑皮层和海马体在这些功能中的核心作用。目前她正在进行一个名为 “曼哈顿迷宫中的小鼠” 项目。


Markus Meister 是 Jieyu Zheng 的导师,1991 年起在哈佛大学担任教授,2012 年于加州理工学院担任生物科学教授,研究领域是大型神经回路的功能,重点关注视觉和嗅觉的感官系统。


Markus Meister 曾于 1993 年被评为 Pew 学者,2009 年因其在视觉和大脑研究方面的贡献获 Lawrence C. Katz 神经科学创新研究奖以及 Minerva 基金会颁发的 “金脑奖”。


新研究发布后,作者们就在 X 上当起了自个儿的自来水。



我们提出的特征是脑科学中最大的未解数值。




Markus Meister 还调侃每秒 10bit 的处理速度可是经过了同行评审的。



随后学术圈各大社区也针对这项研究开始讨论起来。


有人认为论文读起来很有意思,发人深省:



简化内容,只聚焦于中枢神经系统并且将讨论的内容分为内部和外部大脑两部分后,更有意义了。





这是一个非常重要的视角,值得深思……




然鹅,也有不少人提出疑问。



我越想这篇论文中的某些估计,就越怀疑。例如,关于打字员与听者之间比特率的等效性(S.3)似乎有误。正如香农所指出的,英文字母的熵约为每字符 1bit。但如果是一连串的单词或是概念,情况又如何呢?





作者默认了一个假设,即每秒 10bit 是慢的。与我们在硅基底上实现的通用计算系统相比,这的确很慢,但这种假设并不能线性地转化为大脑的信息吞吐量和存在的感知。




对于这项研究,你有什么看法呢?


论文链接:arxiv.org/pdf/2408.10…


参考链接:

[1]http://www.caltech.edu/about/news/…

[2]http://www.cell.com/neuron/abst…

[3]news.ycombinator.com/item?id=424…

[4]arxiv.org/pdf/2408.10…


欢迎在评论区留下你的想法!


—  —


作者:量子位
来源:juejin.cn/post/7492778249534619648
收起阅读 »

为什么一个文件的代码不能超过300行?

大家好,我是前端林叔,掘金小册《如何写出高质量的前端代码》 作者。 先说观点:在进行前端开发时,单个文件的代码行数推荐最大不超过300行,而超过1000行的都可以认为是垃圾代码,需要进行重构。 为什么是300 当然,这不是一个完全精准的数字,你一个页面301行...
继续阅读 »

大家好,我是前端林叔,掘金小册《如何写出高质量的前端代码》 作者。


先说观点:在进行前端开发时,单个文件的代码行数推荐最大不超过300行,而超过1000行的都可以认为是垃圾代码,需要进行重构。


为什么是300


当然,这不是一个完全精准的数字,你一个页面301行也并不是什么犯天条的大罪,只是一般情况下,300行以下的代码可读性会更好。


起初,这只是林叔根据自己多年的工作经验拍脑袋拍出来的一个数字,据我观察,常规的页面开发,或者说几乎所有的前端页面开发,在进行合理的组件化拆分后,页面基本上都能保持在300行以下,当然,一个文件20行也并没有什么不妥,这里只是说上限。


但是拍脑袋得出的结论是不能让人信服的,于是林叔突发奇想想做个实验,看看这些开源大佬的源码文件都是多少行,于是我开发了一个小脚本。给定一个第三方的源文件所在目录,读取该目录下所有文件的行数信息,然后统计该库下文件的最长行数、最短行数、平均行数、小于500行/300行/200行/100行的文件占比。


脚本实现如下,感兴趣的可以看一下,不感兴趣的可以跳过看统计结果。统计排除了css样式文件以及测试相关文件。


const fs = require('fs');
const path = require('path');

let fileList = []; //存放文件路径
let fileLengthMap = {}; //存放每个文件的行数信息
let result = { //存放统计数据
min: 0,
max: 0,
avg: 0,
lt500: 0,
lt300: 0,
lt200: 0,
lt100: 0
}
//收集所有路径
function collectFiles(sourcePath){
const isFile = function (filePath){
const stats = fs.statSync(filePath);
return stats.isFile()
}
const shouldIgnore = function (filePath){
return filePath.includes("__tests__")
|| filePath.includes("node_modules")
|| filePath.includes("output")
|| filePath.includes("scss")
|| filePath.includes("style")
}
const getFilesOfDir = function (filePath){
return fs.readdirSync(filePath)
.map(file => path.join(filePath, file));
}

//利用while实现树的遍历
let paths = [sourcePath]
while (paths.length){
let fileOrDirPath = paths.shift();
if(shouldIgnore(fileOrDirPath)){
continue;
}
if(isFile(fileOrDirPath)){
fileList.push(fileOrDirPath);
}else{
paths.push(...getFilesOfDir(fileOrDirPath));
}
}

}

//获取每个文件的行数
function readFilesLength(){
fileList.forEach((filePath) => {
const data = fs.readFileSync(filePath, 'utf8');
const lines = data.split('\n').length;
fileLengthMap[filePath] = lines;
})
}

function statisticalMin(){
let min = Infinity;
Object.keys(fileLengthMap).forEach((key) => {
if (min > fileLengthMap[key]) {
min = fileLengthMap[key];
}
})
result.min = min;
}
function statisticalMax() {
let max = 0;
Object.keys(fileLengthMap).forEach((key) => {
if (max < fileLengthMap[key]) {
max = fileLengthMap[key];
}
})
result.max = max;
}
function statisticalAvg() {
let sum = 0;
Object.keys(fileLengthMap).forEach((key) => {
sum += fileLengthMap[key];
})
result.avg = Math.round(sum / Object.keys(fileLengthMap).length);
}
function statisticalLt500() {
let count = 0;
Object.keys(fileLengthMap).forEach((key) => {
if (fileLengthMap[key] < 500) {
count++;
}
})
result.lt500 = (count / Object.keys(fileLengthMap).length * 100).toFixed(2) + '%';
}
function statisticalLt300() {
let count = 0;
Object.keys(fileLengthMap).forEach((key) => {
if (fileLengthMap[key] < 300) {
count++;
}
})
result.lt300 = (count / Object.keys(fileLengthMap).length * 100).toFixed(2) + '%';
}
function statisticalLt200() {
let count = 0;
Object.keys(fileLengthMap).forEach((key) => {
if (fileLengthMap[key] < 200) {
count++;
}
})
result.lt200 = (count / Object.keys(fileLengthMap).length * 100).toFixed(2) + '%';
}
function statisticalLt100() {
let count = 0;
Object.keys(fileLengthMap).forEach((key) => {
if (fileLengthMap[key] < 100) {
count++;
}
})
result.lt100 = (count / Object.keys(fileLengthMap).length * 100).toFixed(2) + '%';
}
//统计
function statistics(){
statisticalMin();
statisticalMax();
statisticalAvg();
statisticalLt500();
statisticalLt300();
statisticalLt200();
statisticalLt100();
}

//打印
function print(){
console.log(fileList)
console.log(fileLengthMap)
console.log('最长行数:', result.max);
console.log('最短行数:', result.min);
console.log('平均行数:', result.avg);
console.log('小于500行的文件占比:', result.lt500);
console.log('小于300行的文件占比:', result.lt300);
console.log('小于200行的文件占比:', result.lt200);
console.log('小于100行的文件占比:', result.lt100);
}

function main(path){
collectFiles(path);
readFilesLength();
statistics();
print();
}

main(path.resolve(__dirname,'./vue-main/src'))

利用该脚本我对Vue、React、ElementPlus和Ant Design这四个前端最常用的库进行了统计,结果如下:


小于100行占比小于200行占比小于300行占比小于500行占比平均行数最大行数备注
vue60.8%84.5%92.6%98.0%1121000仅1个模板文件编译的为1000行
react78.0%92.0%94.0%98.0%961341仅1个JSX文件编译的为1341行
element-plus73.6%90.9%95.8%98.875950
ant-design86.9%96.7%98.7%99.5%47722

可以看出95%左右的文件行数都不超过300行,98%的都低于500行,而每个库中超过千行以上的文件最多也只有一个,而且还都是最复杂的模板文件编译相关的代码,我们平时写的业务代码复杂度远远小于这些优秀的库,那我们有什么理由写出那么冗长的代码呢?


从这个数据来看,林叔的判断是正确的,代码行数推荐300行以下,最好不超过500行,禁止超过1000行


为什么不要超过300


现在,请你告诉我,你见过最难维护的代码文件是什么样的?它们有什么特点?


没错,那就是,通常来说,难维护的代码会有3个显著特点:耦合严重、可读性差、代码过长,而代码过长是难以维护的最重要的原因,就算耦合严重、可读性差,只要代码行数不多,我们总还能试着去理解它,但一旦再伴随着代码过长,就超过我们大脑(就像计算机的CPU和内存)的处理上限了,直接死机了。


这是由于我们的生理结构决定的,大脑天然就喜欢简单的事物,讨厌复杂的事物,不信咱们做个小测试,试着读一遍然后记住下面的几个字母:



F H U T L P



怎么样,记住了吗?是不是非常简单,那我们再来看下下面的,还是读一遍然后记住:



J O Q S D R P M B C V X



这次记住了吗?这才12个字母而已,而上千行的代码中,包含各种各样的调用关系、数据结构等,为了搞懂一个功能可能还要跳转好几个函数,这么复杂的信息,是不是对大脑的要求有点过高了。


代码行数过大通常是难以维护的最大原因。


怎么不超过300


现在前端组件化编程这么流行,这么方便,我实在找不出还要写出超大文件的理由,我可以"武断"地说,凡是写出大文件的同学,都缺乏结构化思维和分治思维


面向结构编程,而不是面向细节编程


以比较简单的官网开发为例,喜欢面向细节编程的同学,可能得实现是这样的:


<div>
<div class="header">
<img src="logo.png"/>
<h1>网站名称</h1>
<!-- 其他头部代码 -->
</div>
<div class="main-content">
<div class="banner">
<ul>
<li><img src="banner1.png"></li>
<!-- 省略n行代码 -->
</ul>
</div>
<div class="about-us">
<!-- 省略n行代码 -->
</div>
<!-- 省略n行代码 -->
</div>
</div>

其中省略了N行代码,通常他们写出的页面都非常的长,光Dom可能都有大几百行,再加上JS逻辑以及CSS样式,轻松超过1000行。


现在假如领导让修改"关于我们"的相关代码,我们来看看是怎么做的:首先从上往下阅读代码,在几千行代码中找到"关于我们"部分的DOM,然后再从几千行代码中找到相关的JS逻辑,这个过程中伴随着鼠标的反复上下滚动,眼睛像扫描仪一样一行行扫描,生怕错过了某行代码,这样的代码维护起来无疑是让人痛苦的。


面向结构开发的同学实现大概是这样的:


<div>
<Header/>
<main>
<Banner/>
<AboutUs/>
<Services/>
<ContactUs/>
</main>
<Footer/>
</div>

我们首先看到的是页面的结构、骨架,如果领导还是让我们修改"关于我们"的代码,你会怎么做,是不是毫不犹豫地就进入AboutUs组件的实现,无关的信息根本不会干扰到你,而且AboutUs的逻辑都集中在组件内部,也符合高内聚的编程原则。


特别是关于表单的开发,面向细节编程的情况特别严重,也造成表单文件特别容易变成超大文件,比如下面这个图,在一个表单中有十几个表单项,其中有一个选择商品分类的下拉选择框。


form.png


面向细节编程的同学喜欢直接把每个表单项的具体实现,杂糅在表单组件中,大概如下这样:


<template>
<el-form :model="formData">
<!--忽略其他代码-->
<el-form-item label="商品分类" prop="group">
<el-select v-model="formData.group"
@visible-change="$event && getGr0upOptions()"
>
<el-option v-for="item in groupOptions"
:key="item.id"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
</el-form>
</template>

<script>
export default {
data(){
return {
formData: {
//忽略其他代码
group: ''
},
groupOptions:[]
}
},
methods:{
groupOptions(){
//获取分类信息,赋给groupOptions
this.groupOptions = [];
}
}
}
</script>

这还只是一个非常简单的表单项,你看看,就增加了这么多细节,如果是比较复杂点的表单项,其代码就更多了,这么多实现细节混合在这里,你能轻易地搞明白每个表单项的实现吗?你能说清楚这个表单组件的主线任务吗?


面向结构编程的同学会把它抽取为表单项组件,这样表单组件中只需要关心表单初始化、校验规则配置、保存逻辑等应该表单组件处理的内容,而不再呈现各种细节,实现了关注点的分离。


<template>
<el-form :model="formData">
<!--忽略其他代码-->
<el-form-item label="商品分类" prop="group">
<select-group v-model="formData.group" />
</el-form-item>
</el-form>
</template>

<script>
export default {
data(){
return {
formData: {
//忽略其他代码
group: ''
}
}
}
}
</script>

分而治之,大事化小


在进行复杂功能开发时,应该首先通过结构化思考,将大功能拆分为N个小功能,具体每个小功能怎么实现,先不用关心,在结构搭建完成后,再逐个问题击破。


仍然以前面提到的官网为例,首先把架子搭出来,每个子组件先不要实现,只要用一个简单的占位符占个位就行。


<div>
<Header/>
<main>
<Banner/>
<AboutUs/>
<Services/>
<ContactUs/>
</main>
<Footer/>
</div>

每个子组件刚开始先用个Div占位,具体实现先不管。


<template>
<div>关于我们</div>
</template>
<script>
export default {
name: 'AboutUs'
}
</script>

架子搭好后,再去细化每个子组件的实现,如果子组件很复杂,利用同样的方式将其拆分,然后逐个实现。相比上来就实现一个超大的功能,这样的实现更加简单可执行,也方便我们看到自己的任务进度。


可以看到,我们实现组件拆分的目的,并不是为了组件的复用(复用也是组件化拆分的一个主要目的),而是为了更好地呈现功能的结构,实现关注点的分离,增强可读性和可维护性,同时通过这种拆分,将复杂的大任务变成可执行的小任务,更容易完成且能看到进度。


总结


前端单个文件代码建议不超过300行,最大上限为500行,严禁超过100行。


应该面向结构编程,而不是面向细节编程,要能看到一个组件的主线任务,而不被其中的实现细节干扰,实现关注点分离。


将大任务拆分为可执行的小任务,先进行占位,后逐个实现。


本文内容源自我的掘金小册 《如何写出高质量的前端代码》


作者:前端林叔
来源:juejin.cn/post/7431575865152618511
收起阅读 »

3小时,从0到1上线MVP海外AI网站产品!深度复盘

三、新手3小时极限上线AI产品网站 作为程序员来说,最喜欢务实,不讲虚的。 所以讲完了创业史(具体看这篇:1个人,创业2年心酸史,做各种海外赚美金项目。这一次,你终于悟道了)我们再来讲讲如何3小时极限上线一个AI产品网站。 3.1 什么是AI产品网站出海? A...
继续阅读 »

三、新手3小时极限上线AI产品网站


作为程序员来说,最喜欢务实,不讲虚的。


所以讲完了创业史(具体看这篇:1个人,创业2年心酸史,做各种海外赚美金项目。这一次,你终于悟道了)我们再来讲讲如何3小时极限上线一个AI产品网站。


3.1 什么是AI产品网站出海?


AI产品网站出海,简单来说基于AI技术的产品,通过网站的形式面向海外市场。这不仅仅是语言的翻译,更是对海外用户需求的深度理解和产品的本地化适配。在如今这个AI快速发展的时代,海外市场对AI应用的接受度和付费意愿相对较高,特别是欧美市场。


AI网站出海的核心在于:


技术门槛低:借助现有的开发工具Cursor和AI API大模型,独立开发者也能快速搭建产品


市场需求旺盛:海外用户对AI工具的付费习惯已经形成(比如OpenAI,Claude)


竞争相对较小:相比国内市场,海外AI工具市场仍有大量空白领域


变形路径清晰:订阅制、按次付费等付费模式已被广泛接受。


3.2 为什么选择AI产品网站出海作为创业方向?


3.2.1 个人兴趣和优势


首先我做了5年内核开发程序员,一开始接触知识星球的时候,看到的都是国内各种平台,很明显就不感兴趣。


所以还是打工人的时候,一开始做的项目就是海外工具站。


但是虽然我是程序员,但程序员也分很多种,前端,后端,对于做一个网站,完全没有经验。


当时我记得捣鼓了很久,上线后各种报错,代码完全看不懂,后来就放弃了。


现在,完全不同了。


不需要懂代码,Cursor直接帮你搞定。


当然,要想做出一个成熟的AI产品网站,肯定还是要去学代码的,不然每次编程就和抽卡一样,太随机了。


每当一个bug解决、一个功能实现的实现,程序员的那种成就感油然而生。


其次,我做过很多海外项目,对这一块还是比较熟悉的,所以这些都是我的优势。


自然而然,我应该做AI产品网站出海。


3.2.2 试错成本很低


这里主要是讲资金成本。


相比于我做过的很多海外项目来说,AI产品网站的开发成本特别低。


一个网站:最便宜的几美金一年。


AI编程工具:Cursor(20美金一个月,之前的教育优惠直接免费1年)


其他:都是免费(是的,你没有看错)


下面这张图是网友总结的,可以看到:除了域名和AI编程工具,其他真的是免费的。 (程序员很老实,从来不骗人)



但是,这里要讲下但是,这里讲的是启动资金成本。


如果你的网站有流量了,很大,那你肯定也要投入资金买服务器了。


但这个时候,你也已经开始赚钱了,并且还不少。


所以说,试错成本真的很低。


自从我做过FB跨境电商后,真的再也不想去碰成本这么高的了。


这里还有一个费用,肯定很多人都很关心。


API调用费用


先给大家看一张图,我这次用的photomaker这个API


它一下生成4张图片,才0.0011美金。


从我开发到上线后找人测试,也才花了2.8美金。



并且我的API账号还是之前薅的羊毛,一共两个号,薅了100美金(用不完,完全用不完。)


就算你的网站上线后,你放心,也只会有少量的API调用。


除非很多人用,但这时候你已经开始赚钱了。


我现在用的有:



  1. Claude 4 :


某宝买共享账号,它给你一个账号池,每3个小时可以使用40次,非常方便。


用于写开发者文档,和claude讨论需求。




  1. Cursor pro账号


之前某鱼搞的教育优惠,100多块直接用1年。



  1. 其他


也就上站的时候买一个域名,几美金就行。其他真没了。


3.2.3 市场机会巨大


从个人兴趣和优势出发,不断试错,那也要去能赚到钱的地方是吧。


海外AI工具市场正处于爆发期,用户对新产品的接受度高,愿意为解决实际问题的AI工具付费。


光说没有用,我看看实际案例,我们都喜欢看见再相信。



  1. Pieter Levels


这是一个海外的独立开发者,一个人,做了这么多产品。


而且他所有的收入都列在了他的推上。




  1. 刘小排老师


老外大家可能觉得很遥远,我们看看国内。


一个人,创业后第一个产品就做到了100万月活,只用了1个月,并且做完就放放那了,都没做任何付费推广。




  1. 百里登风


这个人大家可能不太熟悉,这个人就是我(哈哈哈)


从0到1,上线一个MVP产品,用了3个多小时。


我特意用秒表测了一下自己的极限开发速度。


从看到需求到正式上线大概花了3个多小时(包含吃饭时间)。


个人认为还可以继续优化,大概2个小时就差不多可以完成。



这是我开发的产品,10大场景下的AI摄影生成工具。(目前小bug还比较多,当然后面需要慢慢优化,比如登陆界面还没做,支付还没接等等。)



看到现在,大家肯定很枯燥了吧。


所以,我们先来看看我花了3个小时,做出的产品,让你先感受下我的乐趣,或者以后也会成为你的乐趣。


原始图片:



场景一:专业正件照片




场景二:社交和约会照片




场景三:健身锻炼照片




场景四:旅行照片




场景五、婚礼照片




好,不能再放了,再放怕你睡不着。


是不是很牛逼,很逼真,虽然我不知道有没有人做过这种产品,但至少它很有趣,那就可以了。


网站地址:http://www.headshotpro.art/。



  1. 大家


AI时代,每一个人都有机会,每个人都可以做出自己的AI产品网站,所以能看到这里的,都要给大家留个位置。


3.3 如何发现海外AI摄影场景需求?


当然不是我想出来的,自己拍脑袋想出来的几乎都不行。


我是群里看到的,一个网站,一个月13万刀。



这时候,好奇心就来了,这是什么网站?(好奇心往往会有一些发现)


这个网站其中一个功能就是上传自拍,制作自己的AI人物


刚才我才发现,它也有AI场景功能,不过它要输入提示词,我直接固定10个场景。


大家都很懒,肯定会直接吃喂到嘴边的饭,而不是自己去找饭吃,所以固定10个场景,不需要用户输入提示词(这一点很重要)



真正吸引我的是真实感,连眼球都能看清楚。这也太太厉害了,AI一般给人的感觉都很假。


所以我也想开发一个类似的AI摄影图片功能。



其实这一步之后,还需要市场调研,竞品分析,差异化思考。


因为你能想出来的东西,肯定大家都做过了,但不妨碍我们去玩。


是的,你没有看错,就是玩。


3.4 从0到1:3小时极限MVP开发全流程


3.4.1 用claude写需求文档


总算进入正题了,到这你已经看了3908个字,我已经写了一下午加一晚上了,腰都酸了,现在已经22:48分了,奈何就是想写呢。



好,继续(下面的教程大家放心,因为我之前公众号写AI工具使用方法都写的很细,自己都体验过一遍,生怕大家错过每一个步骤。)


看到一个需求后,第一步,不是直接用Cursor实现一个完整的产品,而是先和AI讨论,写一个开发者文档。(这一步很重要)


为什么很重要?这里要说一下。


因为你如果不写这个文档,可能你一边开发,一边脑子里就已经想到一个新功能,做着做着就跑偏了。


很多人觉得写开发者文档很难,需要长篇大论。


其实,不需要。


AI就是你的员工,就是你的伙伴,就是你的合伙人。


比如:我要开发一个AI摄影产品。


你这么说:


我想要开发一个网站,用户上传头像后,为用户创建各种场合的逼真的照片。我们来聊聊这个需求,你觉得应该怎么做?


接下来,你就继续和它聊天,随便聊,就把它当作你的员工,直到你的想法和它的答案对上,就可以了。


比如我说:


我需要10个有痛点需求的场景。


下一步:做出MVP需求文档


你和它说:


你先做MVP,帮我产生一份MVP需求文档,尽量简单。


好,这时候,你的员工就帮你干活了。把这份文档保存在飞书里。


下面的是我让AI生成的需求文档。



这里有一个比较有意思的点,claude 可以生成图文形式的需求文档


给大家看看我的,非常好玩。一目了然。



3.4.2 V0做出产品原型


有了需求文档,不是去直接开发产品了,而是先做个产品原型。


这个就像你想吃鸡腿,你脑海里就会有一个鸡腿的样子(这个叫心理表征,可以看《刻意练习》)


那你现在只有一个文档,没有一个产品的样子,所以先把这个样子做出来。


V0网址:v0.dev/


这里注意一点,我们做一个产品原型,只做壳子就行。具体的功能先不实现,因为具体的功能比较复杂,它比较难做,后面去Cursor里做。


你这样告诉V0:


我要做一个给外国人生成AI摄影图片的产品,使用NextJS框架。


你只需要帮我做一个产品原型,不需要实现具体的功能,


设计的风格尽可能参照小红书的风格。


下面是需求开发文档。(这里你把刚才生成的需求文档复制给他)



然后,等一会,十分钟吧,他就给你生成好了,中间可能会遇到一些报错,直接点击按钮让它修复就可以。


我们来看看具体的效果。





是不是非常不错?


是的,但是我们还需要实现它实际的功能。


3.4.3 Cursor开发实际功能


好,现在我们来真正做实际的功能。



  1. 下载V0生成的代码,点击右上角下载代码。




  1. 打开Cursor,先让Cursor帮你总结下代码功能


告诉Cursor员工:帮我看看我的所有代码,告诉我这个项目干了什么?



  1. 让代码在本地运行起来


总结完之后,我们需要把代码在本地跑起来。


因为V0生成的代码是在他们自己的服务器上运行起来的,我们下载下来后,需要重新在本地运行。


告诉Cursor员工:帮我在本地运行这个项目。


Cursor员工一顿操作后,终于搞定了。


运行命令:npm run dev


就会给你一个地址:



鼠标移动到上面,单击就可以打开,看到网站效果。


如果这时候出现问题,比如网站打开报错,直接截图告诉Cursor员工,同时把终端里的报错信息告诉Cursor员工。


一遍不行两遍,两遍不行三遍,直到修复成功。




  1. 选择合适的API


比如我开发的产品是AI摄影图片,这个时候不知道用什么API。


此时,就可以问claude:


我想做一款产品,用户上传头像后,为用户创建各种场合逼真的照片。我参照的是这个网站:photoai.com。我想知道,有没有现成的API可以让我调用?


好,这个时候claude就会提供各种API。


由于我在fal.ai上有余额,就可以让claude限定在fal.ai上找。


网址:fal.ai/


在上方搜索栏中搜索:photomaker



就出现了这个模型



我们点击API,就可以看到所有的API文档介绍。



这里我们只需要把这个地址链接复制下来,文档都不需要看:


fal.ai/models/fal-…


这里还有一步,你需要创建一个密钥。


4.1 点击账号设置



4.2 点击 API keys



4.3 点击增加密钥



4.4 给它起个名字,根据你的项目来定,比较好分辨。点击创建。



4.5 点击复制,之后把这串密钥保存在你的记事本上。




  1. Cursor实现核心功能


告诉Cursor:


请帮我实现核心功能,使用photomaker API


这是API的说明文档:@ fal.ai/models/fal-…


这是API key:XXX


这里为了安全,API key这个信息比较敏感。


所以我们一般会直接在项目根目录创建一个.env环境变量文件,手动把key进去。


因为Cursor读取不了这个文件。


这里就是不断的调试了,cursor员工自认为干好之后,你就要去检查了。


和之前一样,运行命令:npm run dev


然后在本地调试,测试实际功能。


一旦哪个功能不对,报错,就告诉AI,截图,复制都可以。


最后,一顿操作,你觉得差不多了,就可以了。


3.4.4 将代码提交到Github


在Cursor中开发代码的时候,有可能出现之前改好的功能它又给你改错了,结果可能改了半天的代码都白改了。


点击这里,就可以开始代码管理,初始化仓库。



每次修改完一个主要功能之后,都可以在这里提交一下。最后代码没问题后,我们可以提交到Github。在提交代码之前,我们还要确认下代码是否正确。


运行命令:npm run build


如果像这样全是勾,那就是没问题。



当代码没问题后,点击提交。


这里输入你想在Github上创建的仓库名,选择私有仓库。



最后提交成功。


3.4.5 Vercel部署



  1. 打开vercel,创建一个新项目


网址:vercel.com




  1. 选择部署的项目,点击 导入,点击 部署




  1. 部署成功后添加环境变量,在设置中找到环境变量,把.env文件内的内容放进去。




  1. 开始部署


部署成功后,以后每次提交代码后都可以自动部署。部署不成功的话,可以把logs信息直接复制给Cursor就可以。



3.4.6 购买域名 正式上线



  1. 给网站取名字


域名就是 baidu.com 这种,首先我们要确定给我们的产品网站起一个名字。


比如,我让claude 帮我取了一个,叫:headshotpro



  1. 购买域名


确定好名字之后,去域名注册平台购买域名,比如:Namecheap


购买完成后,就可以去vercel上配置域名了。



3.4.7 上线后的用户测试以及初步反馈


上线之后,只是代表你的产品MVP开发完成了,这只是第一步。


还需要进行用户测试,得到初步的反馈。


比如我把网站发在了各种群里,让用户给我提建议。




这时候,你会得到很多很多建议。比如:






是的,这些都很正常。


但也不是每个问题都要去修复,首先一定要确保核心功能没问题。其他的问题可以先记下来,等后面用户量上来后再修改也不迟。


3.4.8 后续工作


后面还有很多很多工作:


比如:注册、登陆功能


比如:增加各种页面


比如:接入支付功能


比如:每天查看网站数据


比如:每天通过屏幕录制看用户在干什么


虽然事情很多,但是在这个过程中,你会发现很多乐趣。


四、个人成长与收获


4.1 从每日复盘中发现问题


目前的这一切,都源自开始每日复盘,发现自己的问题,然后不断改正。


从复盘中学到了:



  1. 创业要厚脸皮,遇到不懂的,就要问清楚,就算被大佬骂,也要问明白。

  2. 要放下自己的ego,不骄傲,不自大,保持谦卑。不去辩驳,为了一个观点争的面红耳赤。

  3. 要每日复盘,每周复盘,每月复盘。

  4. 带着发现的眼光去体验世界,感受创业,你会发现很多有意思的东西。

  5. 要不断刻意练习,找到自己的导师,及时纠正自己的错误,获得有效的正反馈。

  6. 赚到钱只是一个结果,要不断创造自己的价值。通过自己的专长,找到社会的需求,从而创造价值。


等等。


4.2 目前的收获



  1. 这里非常感谢洋哥,是洋哥拿生命在做的交付,让我能一直坚持下去。从商业IP课到心力课,洋哥一直没有放弃我们。


具体讲讲在破局的收获,以及给新手朋友一点启发。


1.1 首先,看各种精华文章,一开始把破局所有的精华都刷一遍,给自己一个星期的时间去刷。


这里特别注意,看的时候不要焦虑,就把它当作看书。


因为你只有建立赚钱的认知,看过很多案例,才有可能赚到钱。


并且一定要限定时间,不能一直看。


我现在每天都会固定时间看看精华帖和中标。


1.2 看完之后,立马行动,根据自己的兴趣和优势。


比如我参加了很多行动营。不断行动才有机会。


干中学,不断刻意练习,遇到不懂的就在群里问,教练就是你的导师,可以不断指出你的问题,获得及时有效的正反馈。





所以一定要积极去参加行动营,这些都是低成本尝试,只有做,才有结果,只是一直想,特别耗费心力。


事情是做出来的,而不是想出来的。


1.3 其实最重要的是线下组局。


也正是在洋哥的鼓励下,我组了第一次局,当时来了好多小伙伴,并且大家都非常年轻,来自周边城市,南京的,苏州的小伙伴也都赶了过来。


大家聊的很爽,还一起吃了晚上。



我现在的一起赚钱小群有4个人,有两个都是那天线下组局认识的,大家在群里一起分享认知,收获,一起互相鼓励。


创业路上需要这样一群人,一群志同道合的人。


还有北京行动家大会,一共3天,真的是头脑风暴,大家一聊聊到凌晨,一天就睡4个小时。


在回来的高铁上,看着洋哥给的《超级个体 从0到百万变现》,写下了下面这么多感悟。



1.4 还有洋哥用生命的交付


从一开始的商业IP课到产品课,心力课等等,各种各样的课程。这价值我就不说了,生怕大家跑不出来。


各种密训,各种直播。


我的手机里全都是洋哥的录屏,常听常新。


焦虑了,听一听,缓解缓解。


迷茫了,听一听,找找方向。


没有动力了,听一听,打个鸡血,继续往前。



这里建议大家还是看直播,因为录屏后肯定不会去看,看直播的效果最好。


真的,只要你不放弃自己,什么时候都有可能。每个人都有自己的节奏,按照自己的节奏来,成功只是时间问题。


目前的成绩:


今天写的这篇公众号已经到了400多阅读,目前还在上涨。



后面,继续努力,争取做出自己的IP,再次感谢洋哥。



  1. 感谢惰总凌晨3点还在群里给我们解决问题


就怕我们赚不到钱,都要直接投喂了。



是惰总让我知道了事前逻辑。


创业,做项目一定不能用事后逻辑,别人的成功是不可复制的。时刻用事前逻辑,根据自己的优势、经历、资源来选择你的创业项目,形成自己的创业选品逻辑。


一个财富自由的大佬居然愿意每个月带着我出去跑一次,我何德何能啊。这个多大价值就不说了吧,再次感谢惰总。




  1. 感谢刘小排老师,是刘小排老师让我明白了做产品可以这么快乐。


小排老师每次都会在视频结尾说一句类似的话:赶紧去玩起来吧。玩个一整天吧。


是啊,玩起来,跟着自己的兴趣,不断探索,多有意思啊。


这些都是我创业路上的贵人,能及时发现你的问题,给你提供有效的正反馈。


也希望大家都能找到自己的乐趣,去吧,赶紧去玩起来吧!


tips:


好了,今天写完了AI网站产品的复盘,如果点赞多的话,下一篇就会很快与大家见面了(预告:一个完全不懂代码的新手(我女朋友),从0到1,做出一款类似forest的专注森林,学习倒计时APP,目前已经上架。)


技术完全没有门槛,一个拼创意的时代来了!


学会了或有启发,别忘了给我点个赞,评论,转发~因为你的反馈真的很重要!


最后,如果你对AI网站出海感兴趣,欢迎关注公众号 百里登风AI


加 luffy10004 ,领取一份《AI网站出海新手指南》资料包。


作者:百里登风AI出海
来源:juejin.cn/post/7517841519253848116
收起阅读 »

别在用“长期主义”骗自己了

引言 上篇文章,一个读者评论问,如何在看不到结果的时候,还能坚持下去。 我内心里立刻蹦出来四个字:长期主义,不过转念一想这不是正确的废话吗,现在这个社会谁还没听过长期主义? 坚持早起、坚持阅读、坚持健身,仿佛你足够坚持,命运就会回报你,长期主义本身都快成了一种...
继续阅读 »

引言


上篇文章,一个读者评论问,如何在看不到结果的时候,还能坚持下去。


我内心里立刻蹦出来四个字:长期主义,不过转念一想这不是正确的废话吗,现在这个社会谁还没听过长期主义?


坚持早起、坚持阅读、坚持健身,仿佛你足够坚持,命运就会回报你,长期主义本身都快成了一种政治正确。


我很庆幸当时没把这几个字回复给读者,那也太不负责任了。


因为我发现,很多人理解的长期主义,是错的,包括我自己。


试想你有没有这种感觉,每天都在坚持做一些你认为正确的事,但一边焦虑的等待结果为什么还不来,一边痛苦的咬牙坚持。


你有没有想过真正的长期主义,到底是什么样的?


长期主义的难点从来不是坚持,而在于你能否坚定方向、建立反馈,并且在走错路时愿意纠正它。


长期主义的误区


误区一:把长期主义当作“迟到的确定性”


我一度以为,长期主义是一个慢热的公式,只要你足够努力、足够坚持,总会有回报,只不过回报来的慢了一些。


上学的时候,老师教育我们坚持学习,成绩自然会提升。后来看到各种鸡汤文章,看到很多诸如“他默默努力十年,终于爆红”、“她写了一千篇文章,终于年入百万”这样的励志故事。


于是我陷入了第一个陷阱,把长期主义当作“迟来的确定性”,我一直在等待短期反馈出现。


就像我刚开始写文章时,我会在文章发布后,不断的点击刷新按钮,在后台查看数据,看看曝光量怎么样、阅读量怎么样。


不少自媒体人都会有这种“数据焦虑”,如果阅读量涨得很快,那就无比开心,如果发出去半小时没人看,就会陷入焦虑。


那个时候,我自诩是在践行长期主义,但其实我无时无刻都在期待短期的奖励。


但当你这篇文章发出去,内心期待着这篇文章能够达到“10w+”的时候,你就已经悄悄背离了长期主义。


真正的长期主义,不需要靠短期反馈也能坚持下去。


误区二:把坚持当成意义本身


那你说,我不在意短期反馈,我有足够的毅力坚持,总可以了吧?


这就聊到容易陷入的第二个误区,把“坚持”当成了意义本身


今年年初的时候,我已经坚持写作一年,可是涨粉和阅读量都不尽人意。而且AI发展一日千里,见到很多人走AI赛道涨粉很快,用AI写的文章,靠AI堆上量也能出爆文,内心非常焦虑,我思考是不是自己走错了方向。


屋漏偏逢连夜雨,我感觉耗尽了自己的灵感,没有想写的选题,并且对之前的内容特别不满意,想改变也无从下手。


但我不敢停下,我选择了咬牙坚持,逼迫自己大量的看书、看专栏,试图找到更多灵感。强迫自己多记录一些东西,用笔记数量带给自己安慰。


结果就是看过的内容都是走马观花,什么都没记住。更新的几篇文章全部都绞尽脑汁,即使筋疲力尽写完后也只剩下对自己的不满。


回想起来,那段时间我只是在靠机械的阅读和别扭的写作,来逃避自己没有方向的现实而已。


说难听点就是低水平重复。


如果在错误的地方坚持,那只能带来更大的错误。


真正的长期主义,不会让自己痛苦的坚持,而是建立在对方向的清晰判断上。


什么是真正的长期主义


现在看来,真正理解长期主义并不难,可以用一个公式来总结:长期主义 = 有方向(战略判断)× 有反馈(系统纠偏)× 有预期(心理预期)。


这是一个乘法模型,只要其中任意一项为零,结果就是零。


有方向


你之所以能长期坚持一件事,是因为你能看到这件事长远来看带来的价值。


就拿阅读、写作、锻炼来说,是公认的需要长期主义的事情,虽然他们的反馈周期很长,但是它们能够给我们带来的正向价值十分确定。


可就是最简单直接的三件事情,为什么还是坚持不下来?


这不仅是意志力的问题,还与我们大脑的结构有关——我们天生不擅长做长期决策。


有一本讲脑科学的书《权衡一念》,作者福尔克从脑科学的角度介绍了一个概念:我们大脑有一个「自我相关系统」,当你每次想到与自我相关的东西,核磁共振成像就会扫描到这个区域在被点亮。


但是当你想到几年后的自己或者老年的自己时,「自我相关系统」却不会被点亮,也就是说我们甚至会把「未来的自己」想像成另一个人。


pexels-pascal-claivaz-66964-243170.jpg


我们以为自己明白一些事情在未来带给我们的好处,但是大脑却认为这些东西和“自己”无关,于是我们更倾向就是自动聚焦到眼前的事情,忽略未来、长远的好处,于是没办法建立方向感。


因为眼前事情,给我们的感受最直接,所以我们陷入了期待短期回报的误区。


你想要在你认可的方向上坚持下去,有一种最简单的方式是,改变聚焦点


不是强迫自己坚持,而是把注意力转向能够在当下带给你满足感的元素。


怎么改变聚焦点?我举两个自己的例子。


前一阵子为了买东西再次下载了抖音,结果一发不可收拾,开始习惯性的用碎片时间刷短视频。


之前我是全凭意志力控制自己,不断给自己强调“别刷了,没营养”,并告诫自己多看些书。但这次我找出了我最喜欢一本小说《挪威的森林》,这本书我读过五遍,能够很自然的就沉浸在小说的情节里,等小说看完,我空闲时已经不会在习惯性的拿出手机刷短视频了。


日常因为工作原因一坐就是一天,但我又知道每天至少得保证7000步才是最健康的。当我认为需要运动的时候,我并不是告诉自己多运动才能长寿,而是劝自己,文章写到这里灵感已经枯竭,不如出去走一走换换脑子。


这里要点是,我们尽量去聚焦到那些我们不愿意去改变的事情,当下能给我们带来的好处,甚至说和我们喜欢的事情绑定在一起。


聚焦点不一样,行动方向截然不同,真正的长期主义,不是压抑自己做不喜欢的事情,而是和自己喜欢的事情“打配合”。


有反馈


许多人之所以无法坚持长期主义,是因为人很容易在前进的路上迷失。


一个关键原因是我们不能仅凭意志力在黑暗中前行,反馈就是我们的灯塔,提醒自己是否还在正确的方向。


但如果没有建立自己的反馈体系,就很容易陷入把坚持当成意义这个误区。


系统动力学把反馈分成了正反馈回路和负反馈回路。


正反馈就是结果反过来加强了原因,从而形成螺旋式上升。如果你文章质量好,获得了大量点赞,因此平台持续给你推荐。推荐又让更多的人看到,别人进一步的点赞、转发。


负反馈就是系统对偏差进行修复,来保障稳定和持续。健身时你不断冲击更大重量,但身体终会在某一重量时无法承受,你可能会因此受伤,反而达不到之前你能坚持的最大重量。


那么我们就很清晰了,正反馈帮助我们进步,负反馈帮助我们纠偏,你必须建立自己的反馈系统。


第一类反馈来源于外界


你有没有发现很多博主在视频或者文章后面,都在求大家给一个一键三连,我曾以为这是什么套路,现在看来这是每一个创作者的本能,你的点赞、评论、转发,是对一个内容创作者最好的奖赏。


坦率的讲,现在这个快节奏社会,能够沉下心看完一篇不知名作者写的一篇几千字的文章,已经足够让我开心。


哪怕是我自己,能让我踏下心看完几千字文章的,都是那些大IP和知名的专栏作家。


如果收到了点赞和转发,那我更是无比感激,即使到了今天,我看到文章的互动依然会很兴奋。


这是极强的正反馈,会给你继续前进的力量,随后螺旋上升。


哦对,看到这确认不点个赞吗?


可并不是每次努力,都能够听到外界带给你正向的声音。


pexels-ann-h-45017-32342293.jpg


因此第二类反馈来源于你自己


我文章有过很长一段时间的低谷期,几千字的文章无人问津,就好像你搬起了一大块石头扔进水里,一点水花都没有。


那时候我就意识到,我必须建立“内部反馈机制”,我不断问自己几个问题:



  1. 学习到的知识,我自己是否真正理解了?

  2. 如果理解了,能不能用自己的话把这个道理讲出来?

  3. 这个东西,我有没有应用到真实的生活中,给自己带来改变?


慢慢的我发现,曾经让自己迷茫、愤怒、无助的事情,越来越少了。我逐渐能够看透本质,理清思路、看清全局。


其实写作带来这些好处已经弥足珍贵,但我认为还不够,我开始反思每一篇文章:



  1. 这篇文章的逻辑好不好,能不能做到自洽,衔接是否通顺?

  2. 是不是论点不够、思考不够,导致文章没有说服力?

  3. 文章节奏控制的怎么样,情绪有没有断层?


再比如最近我自己正在拆解每篇文章的不足,然后有意识的和高手学习并一点点改进,一天写完的内容,可能修改要花上三天。


虽然拆解不足给自己的是负反馈,但是复反馈能够帮助你纠偏。


正是这个内部反馈系统,让我坚持到了现在。


第三类设计你自己的系统反馈


最强大的反馈系统,不靠别人、不靠情绪,而是系统本身。


B站有一个up主叫做影视飓风,老板Tim分享了他们的内容复盘系统,他在最显眼的地方专门放了一个屏幕,里面记录了每一个内容各种实时数据,通过图表展现出来,全公司的人都可以看见。


他们分析哪些内容能涨粉、哪些容易爆,哪条视频表现不好、为什么表现不好。正是这种高度透明和数据驱动的机制,一定程度上帮助他们孵化出第二个账号“飓多多StormCrew”,内容风格完全不同,却因为精准抓住观众喜好而大获成功。


这块我做的不好,我之前几乎不去复盘内容数据,受到他的启发,我花了15分钟用飞书的多维表格,给自己搭建了一个内容数据看板,这里面记录了自己今年来的文章阅读走势。
image.png
波动这么明显我有点汗颜,不过我发现带有30+、面试、AI相关的内容,大家会更感兴趣些。


你不一定要搭建看板,但你可以从每周一次总结开始,从定期记录自己的感受开始,找到合适自己的反馈机制。


有预期


最后我们聊聊,如果你真的想要践行长期主义,你得做好哪些准备。


毕竟长期主义并不轻松,提前把困难都想到, 那么真的遇到困难时,反而更容易坚持下来。


长期主义,需要你持续付出。


它不是简单的重复,而是不断在你的“认知边界”上试错、突破。


这很枯燥,而且往往没有立刻回报,还意味着一次次笨拙的表达、失败的尝试,甚至别人眼里的“不够好看”。


但你要相信:每一次认真而笨拙的输出,都是自己能力的提升。


长期主义,需要你学会拒绝。


在这个快节奏的社会,你会看到身边的人,靠短视频一夜爆红,靠AI一键搬运赚取时代红利,也会看到一些小伙伴踩对节奏,迅速赚到了第一桶金。


而你却在钻研技能、搭建反馈系统、耐心苦练内功。


你要拒绝那种“快速反馈”的甜头,转而相信“慢反馈”的确定性。


长期主义的回报,是非线性的。


你以为努力一点,进步一点,实际上看似停滞许久,在某一天突然爆发。


大模型有一个著名的现象,叫做能力涌现:你喂进去足够多的数据,在某一刻,它突然学会了你没教它的东西,比如逻辑推理、语言翻译,甚至写代码。


这不是持续进化,而是能力突然“跃迁”。可能连大模型科学家本身也不明白,AI怎么就突然变得如此强大。


就像你健身半年没有什么变化,突然在某一天,你惊讶的发现:肌肉线条已经若隐若现。


说在最后


要我看来,长期主义最大的坏处就是孤独。


你给自己选中了一条要走下去的路,可能身边的人不理解,就算是是最亲近的人对你冷言冷语,你也没有抱怨的权利。


不过长期主义最大的好处也在这里。


你真的会一次次得把曾经以为的“天花板”变成自己脚下的阶梯,你除了抱怨时间不够、能力不足、精力不够,你没什么好抱怨的。


而这,恰恰就是一种美好的人生状态!


这是东东拿铁的第82篇原创文章,欢迎关注。


作者:东东拿铁
来源:juejin.cn/post/7516846036586102835
收起阅读 »

离职后,我的第一个出海产品上线了

今天,我的第一个独立开发出海产品 Chat2Report 上线了,这是一款基于 RAG 的美股财报聊天应用。 为什么要开发独立产品 去年初通过几位大佬(越南的 Tony Dinh,国内的 Hawstein 和 vikingz)的博客了解到,作为程序员还有开发...
继续阅读 »

今天,我的第一个独立开发出海产品 Chat2Report 上线了,这是一款基于 RAG 的美股财报聊天应用。


image.png


为什么要开发独立产品


去年初通过几位大佬(越南的 Tony Dinh,国内的 Hawstein 和 vikingz)的博客了解到,作为程序员还有开发独立产品出海这一条路,其中有些收入还不错,甚至有开发者辞掉了工作,全职做独立开发。


image.png


看完他们的文章,心里很激动,想着自己是不是也可以试一试。于是使用 OpenAI 的 gpt-4o-mini 模型微调了一个专门的模型,做了一个变量命名工具,叫 VarNamer,支持多国语言,用户输入任意语言,即可输出精简的英文变量。当时 AI 编程工具还刚刚兴起,变量命名又是件头痛的事,所以想着这个工具应该能为自己节省不少时间。


其实当时开发这个产品,也是为了学习新技术,为自己后面开发出海产品做准备,由于看到不少独立产品都是桌面端的,所以基于 Electron + Vue3 做了 VarNamer,为什么选择 Electron?因为它构建跨平台程序非常方便,为了上Mac,还购买了苹果开发者证书。


image.png


开发 VarNamer 并不顺利,期间踩了不少坑,也坚定了后面的出海产品不会再做桌面端了。因为一般的 Web 开发不需要考虑版本更新、证书、跨平台兼容等问题,但是开发桌面应用需要将这些因素都考虑进去。除去后端服务器的成本,安装包托管,更新逻辑,还需要考虑程序的签名证书,不然用户安装应用会报警告,甚至安装不了,其中苹果开发者证书一年就99刀,Windows 就更贵了。


VarNamer 上线后,在几个论坛发了贴宣传,也发给了同事使用,反响还不错,但是没想到后面 AI 编程工具发展这么快,特别是出了 Cursor 这样的王炸产品,变量命名完全不是难事,几乎改变了以往的编程习惯,一直 Tab 的感觉,简直不要太爽。


99 刀的苹果开发者证书就开发了一个应用,着实太浪费了,至于 VarNamer,后面再也没管过它,好像域名最近快到期了,也不打算续费了。


独立出海产品契机


自 VarNamer 之后,接下来的几个月时间并没有开发新的产品,为什么?因为我不知道开发什么,好像也找不到什么痛点需要解决的,后面想到自己在买一家上市公司的股票之前,会分析公司的财务报告,毕竟我是一位追随彼得·林奇和巴菲特的价值投资者,哈哈!


但是分析财报是件麻烦且费脑的事,一份财报少则几十页多则几百页,除了重点关注三张报表,即资产负债表、利润表、现金流量表(俗称“三大表”),还需要关注管理策略、管理层的措施、战略,财报中是否有欺诈风险等。


既然这么麻烦,那 AI 是不是能帮我们分析了?后面经过调研发现了市面上还真有这样的产品,比如 beebee、reportify,它们都是基于 RAG 实现的,但是我想基于它们开发一款新的产品,为什么?因为它们的功能实在太多了,新闻、电话会议、上传文件、公司评价...,而且 RAG 也不精准,我需要一款操作简单,体验更好,简洁、美观,精准,专门分析财报的工具。


image.png


去年 9 月下旬开始了技术调研,之前对 RAG 技术稍微有点了解,但是不够深入,只是基于 Dify 做了一些应用,同时发现 Dify 不够自由,文档解析分块不能自定义元数据,后端又是基于Flask的,to C 的应用担心性能不够,生产环境还需要一台服务器额外部署 Dify。


调研下来最终确定业务层使用Go + Gin, 大模型层使用Python + FastAPI + LlamaIndex,前端使用Vue3。LlamaIndex 实现 RAG 应用非常方便,兼容各种第三方文档解析器、向量模型(Embedding models)、重排序模型(Rerank models), 向量数据库、大语言模型(LLMs)。


image.png


之后利用下班时间和假期实现了个 demo,感觉还不错,是自己想要的效果,美股财报批量转 PDF,文档批量解析、分块,提取布局信息,前端布局重构回溯,AI回答带引用来源,高亮定位到原文段落,一个 ChatPDF + AI 财报助理的构想应该很快就可以实现。


10 月份利用业余时间开始了马不停蹄的开发,这期间公司一些事件却让自己很不舒服,作为一个技术人,希望能全身心的投入到技术中,利用技术解决问题,但是各种PPT汇报、职场PUA,让自己疲于奔命。


我想离职了,全职投入到项目开发中,11月初的一个晚上把这个想法告诉了老婆,非常正式的讲了自己的规划,产品怎么落地,产品受众人群,怎么盈利,以及一个粗略的计划,希望得到她的支持。因为我觉得,组建家庭后,另一半相当于就是你的人生合伙人。在很多重要决策上,得到合伙人的支持,才能走得更好走得更远。如果成功了,兴许以后就不用上班了,就算失败了大不了重新找个班去上。老婆没说什么,表示了支持,在这里要特别感谢一下老婆。


全力加速开发


12 月 09 号是我最后一个工作日,也是我作为全职独立开发的第一天,当天走出公司,呼吸着新鲜的空气,感受到了从未有过的自由。


成为全职独立开发之后,最大的感受就是开发效率提高了几倍,不用再参加枯燥无聊的会议,应付各种办公室政治斗争,输出无意义的PPT。直到今天项目上线,全部开发时间应该是3个月。


这期间踩了无数坑,以前工作时的一些优点,现在反而成了缺点,比如之前专注于写好代码,追求架构完美和扩展性,甚至有代码洁癖,但这严重推迟了产品的上线时间,在产品还未经过市场验证之前,应该快速推出产品,验证市场需求,这比追求精美更重要。


接下来的计划


接下来的主要任务就是宣传了,去海外各大社区宣传寻找目标用户,比如 Facebook、Twitter、Reddit。


两个月之后我会再写一篇帖子,分享我的成果,盈利情况等。


接下来也会分享一些出海产品在技术选型和海外支付方面的经验。


作者:geekbing
来源:juejin.cn/post/7517998609946673186
收起阅读 »

离职后的这半年,我前所未有的觉得这世界是值得的

大家好,我是一名前端开发工程师,属于是没有赶上互联网红利,但赶上了房价飞涨时代的 95 后社畜。2024 年 3 月份我做了个决定,即使已经失业半年、负收入 10w+ 的如今的我,也毫不后悔的决定:辞职感受下这个世界。 为什么要辞职,一是因为各种社会、家庭层面...
继续阅读 »

大家好,我是一名前端开发工程师,属于是没有赶上互联网红利,但赶上了房价飞涨时代的 95 后社畜。2024 年 3 月份我做了个决定,即使已经失业半年、负收入 10w+ 的如今的我,也毫不后悔的决定:辞职感受下这个世界


为什么要辞职,一是因为各种社会、家庭层面的处境对个人身心的伤害已经达到了不可逆转的程度,传播互联网负面情绪的话我也不想多说了,经历过的朋友懂得都懂,总结来说就是,在当前处境和环境下,已经没有办法感受到任何的快乐了,只剩焦虑、压抑,只能自救;二是我觉得人这一辈子,怎么也得来一次难以忘怀、回忆起来能回甘的经历吧!然而在我的计划中,不辞职的话,做不到。


3 月


在 3 月份,我去考了个摩托车驾-照,考完后购买了一辆摩托车 DL250,便宜质量也好,开始着手准备摩旅。


webwxgetmsgimg.jpg


4 月份正式离职后,我的初步计划是先在杭州的周边上路骑骑练下车技,直接跑长途还是很危险的,这在我后面真的去摩旅时候感受颇深,差点交代了。


4 月


4.19 号我正式离职,在杭州的出租屋里狠狠地休息了一个星期,每天睡到自然醒,无聊了就打打游戏,或者骑着摩托车去周边玩,真的非常非常舒服。


不过在五一之前,我家里人打电话跟我说我母亲生病了,糖尿病引发的炎症,比较严重,花了 2w+ 住院费,也是从这个时候才知道我父母都没有交医保(更别说社保),他们也没有正式、稳定的工作,也没有一分钱存款,于是我立马打电话给老家的亲戚让一个表姐帮忙去交了农村医保。所有这些都是我一个人扛,还有个亲哥时不时问我借钱。


381728547058_ 拷贝.jpg


说实话,我不是很理解我的父母为什么在外打工那么多年,一分钱都存不下来的,因为我从小比较懂事,没让他们操过什么心,也没花过什么大钱。虽然从农村出来不是很容易,但和周围的相同条件的亲戚对比,我只能理解为我父母真的爱玩,没有存钱的概念。


我可能也继承了他们的基因吧?才敢这样任性的离职。过去几年努力地想去改变这个处境,发现根本没用,还把自己搞得心力交瘁,现在想想不如让自己活开心些吧。


5 月


母亲出院后,我回到杭州和摩友去骑了千岛湖,还有周边的一些山啊路啊,累计差不多跑了 2000 多公里,于是我开始确立我的摩旅计划,路线是杭州-海南岛-云南-成都-拉萨,后面实际跑的时候,因为云南之前去过,时间又太赶,就没去云南了。


2024-10-11 103931.jpg


6 月


在摩友的帮助下,给摩托车简单进行了一些改装,主要加了大容量的三箱和防雨的驮包,也配备了一些路上需要的药品、装备,就一个人出发了。


2024-10-11 103949.jpg


从杭州到海南这部分旅行,我也是简单记录了一下,视频我上传了 B 站,有兴趣的朋友可以看看:


拯救焦虑的29岁,考摩托车驾-照,裸辞,买车,向着自由,出发。


摩托车确实是危险的,毕竟肉包铁,即使大部分情况我已经开的很慢,但是仍然会遇到下大雨路滑、小汽车别我、大货车擦肩而过这种危险情况,有一次在过福建的某个隧道时,那时候下着大雨,刚进隧道口就轮胎打滑,对向来车是连续的大货车,打滑之后摩托车不受控制,径直朝向对向车道冲过去,那两秒钟其实我觉得已经完蛋了,倒是没有影视剧中的人生画面闪回,但是真的会在那个瞬间非常绝望,还好我的手还是强行在对龙头进行扳正,奇迹般地扳回来且稳定住了。


过了隧道惊魂未定,找了个路边小店蹲在地上大口喘气,雨水打湿了全身加上心情无法平复,我全身都是抖的,眼泪也止不住流,不是害怕,是那种久违地从人类身体发出的求生本能让我控制不住情绪的肆意发泄。


在国道开久了人也会变得很麻木,因为没什么风景,路况也是好的坏的各式各样,我现在回看自己的记录视频,有的雨天我既然能在窄路开到 100+ 码,真的很吓人,一旦摔车就是与世长辞了。


不过路上的一切不好的遭遇,在克服之后,都会被给予惊喜,到达海南岛之后,我第一次感觉到什么叫精神自由,沿着海边骑行吹着自由的风,到达一个好看的地方就停车喝水观景,玩沙子,没有工作的烦扰,没有任何让自己感受到压力的事情,就像回到了小时候无忧无虑玩泥巴的日子,非常惬意。


稿定设计导出-20241011-112615.jpg


在完成海南环岛之后,我随即就赶往成都,与前公司被裁的前同事碰面了。我们在成都玩了三天左右,主要去看了一直想看的大熊猫🐼!


2024-10-11 174426.jpg


之后我们在 6.15 号开始从成都的 318 起始点出发,那一天的心情很激动,感觉自己终于要做一件不太一样的事,见不一样的风景了。


401728642422_.pic.jpg


小时候在农村,读书后在小镇,大学又没什么经济能力去旅行,见识到的事物都非常有限,但是这一切遗憾在川藏线上彻底被弥补了。从开始进入高原地貌,一路上的风景真的美到我哭!很多时候我头盔下面都是情不自禁地笑着的,发自内心的那种笑,那种快乐的感觉,我已经很久很久很久没有了。


稿定设计导出-20241011-184041.jpg


同样地,这段经历我也以视频的方式记录了下来,有兴趣的朋友可以观看:


以前只敢想想,现在勇敢向前踏出了一步,暂时放下了工作,用摩托跑完了318


到拉萨了!


411728642433_.pic.jpg


花了 150 大洋买的奖牌,当做证明也顺便做慈善了:)


421728642441_.pic_h111d.jpg


后面到拉萨之后我和朋友分开了,他去自驾新疆,我转头走 109 国道,也就是青藏线,这条线真的巨壮美,独自一人行驶在这条路,会感觉和自然融合在了一起,一切都很飘渺,感觉自己特别渺小。不过这条线路因为冻土层和大货车非常非常多的原因,路已经凹凸不平了,许多炮弹坑,稍微骑快点就会飞起来。


这条线还会经过青海湖,我发誓青海湖真的是我看到过最震撼的景色了,绿色和蓝色的完美融合,真的非常非常美,以后还要再去!


2024-10-11 185558.jpg


拍到了自己的人生照片:


2024-10-11 185623.jpg


经历了接近一个半月的在外漂泊,我到了西宁,感觉有点累了,我就找了个顺丰把摩托车拖运了,我自己就坐飞机回家了。


这一段经历对我来说非常宝贵,遇到的有趣的人和事,遭遇的磨难,见到的美景我无法大篇幅细说,但是每次回想起这段记忆我都会由衷地感觉到快乐,感觉自己真的像个人一样活着。


这次旅行还给了我感知快乐和美的能力,回到家后,我看那些原来觉得并不怎么样的风景,现在觉得都很美,而且我很容易因为生活中的小确幸感到快乐,这种能力很重要。


7 月


回到家大概 7 月中旬。


这两个多月的经历,我的身体和心态都调整的不错了,但还不是很想找工作,感觉放下内心的很多执念后,生活还是很轻松的,就想着在家里好好陪陪母亲吧,上班那几年除了过年都没怎么回家。


在家里没什么事,但是后面工作的技能还是要继续学习的,之前工作经历是第一家公司用的 React 16,后面公司用的是 Vue3,对 React 有些生疏,我就完整地看了下 React 18 的文档,感觉变化也不是很大。


8、9 月


虽然放下了许多执念,对于社会评价(房子、结婚、孩子)也没有像之前一样过于在乎了,但还是要生活的,也要有一定积蓄应对未来风险,所以这段时间在准备面试,写简历、整理项目、看看技术知识点、刷刷 leetcode。


也上线了一个比较有意义的网站,写了一个让前端开发者更方便进行 TypeScript 类型体操的网站,名字是 TypeRoom 类型小屋,题源是基于 antfu 大佬的 type-challenges


目前 Type Challenges 官方提供了三种刷题方式



这几种方式其实都很方便,不过都在题目的可读性上有一定的不足,还对开发者有一定的工具负担、IDE 负担。


针对这个问题,也是建立 TypeRoom 的第一个主要原因之一,就是提供直接在浏览器端就能刷题的在线环境,并且从技术和布局设计上让题目描述和答题区域区分开来,更为直观和清晰。不需要额外再做任何事,打开一个网址即可直接开始刷题,并且你的答题记录会存储到云端。


欢迎大家来刷题,网址:typeroom.cn


截屏2024-10-12 21.53.26.png


因为个人维护,还有很多题目没翻译,很多题解没写,也还有很多功能没做,有兴趣一起参与的朋友可以联系我哦,让我一起造福社区!


同时也介绍下技术栈吧:


前端主要使用 Vue3 + Pinia + TypeScript,服务端一开始是 Koa2 的,后面用 Nest 重写了,所以现在服务端为 Nest + Mysql + TypeORM。


另外,作为期待了四年,每一个预告片都看好多遍的《黑神话·悟空》的铁粉,玩了四周目,白金了。


WechatIMG43.jpg


现在


现在是 10 月份了,准备开始投简历找工作了,目前元气满满,不急不躁,对工作没有排斥感了,甚至想想工作还蛮好的,可能是闲久了吧,哈哈哈,人就是贱~


更新 11 月


我还是没有找工作,又去摩旅了一趟山西、山东,这次旅行感觉比去西藏还累、还危险。同样是做了视频放 b 站了,有兴趣的可以看看:


骑了4300km只为寻找那片海-威海的海|摩旅摩得命差点没了


真的要开始找工作了喂!


最后


其实大多数我们活得很累,都是背负的东西太多了,而这些大多数其实并不一定要接受的,发挥主观能动性,让自己活得开心些最重要,加油啊,各位,感谢你看到这里,祝你快乐!


这是我的 github profile,上面有我的各种联系方式,想交个朋友的可以加我~❤️


作者:vortesnail
来源:juejin.cn/post/7424902549256224804
收起阅读 »

Swift 官方正式支持 Android,iOS 的跨平台春天要来了吗?

近日,Swift 官方正式宣布成立 Android 的工作组,将 Android 列为官方支持的平台,该工作组的主要目标是为 Swift 语言添加并维护 Android 平台支持,让开发者能够使用 Swift 开发 Android 应用: 其实 Swift ...
继续阅读 »

近日,Swift 官方正式宣布成立 Android 的工作组,将 Android 列为官方支持的平台,该工作组的主要目标是为 Swift 语言添加并维护 Android 平台支持,让开发者能够使用 Swift 开发 Android 应用:



其实 Swift 语言跨平台支持也不是什么新鲜事,在之前我聊过的 Skip 用 Swift 写 Android App 的时候就聊过,只是不同的是 Skip 是将 Swift 翻译成 Kotlin,把 SwiftUI 翻译成 Compose 的形式来实现,这和 uni-app x 的跨平台实现殊途同归。



感兴趣的可以看 《2025 跨平台框架更新和发布对比》



但是 Swift 官方的方案则不同,它是通过 LLVM 进行适配的,我们之前聊过的 《为什么跨平台框架可以适配鸿蒙》就聊过,LLVM 也是各大框架适配鸿蒙的重要基石,甚至一些方案适配鸿蒙是通过 Apple 的 LLVM 去先导出 IR 来完成前置工作。


而这次 Swift on Android 的实现,则是直接利用 Android 平台的构建工具:Android NDK 。


为什么这么说?因为 Swift 编译器从诞生之初就基于 LLVM ,而 Google 的 Android NDK 后来也使用基于 LLVM 的 Clang 作为其官方 C/C++ 编译器 :



  • NDK r11 开始建议切换到 Clang

  • NDK r12 ndk-build 命令默认使用 Clang

  • NDK r13 GCC 不再受支持

  • NDK r14 GCC 弃用

  • ····



说起 Clang 和苹果也是很有渊源,Clang 的设计初衷是提供一个可以替代 GCC 的前端编译器,因为 GCC 的发展不符合 Apple 的节奏和需要,同时受限于License,苹果公司无法使用 LLVM 在 GCC 基础上进一步提升代码生成质量,因此苹果公司决定从头编写 C、C++、Objective-C 语言的前端 Clang,以彻底替代GCC



而在编译上,比如 stdlib 里的 AddSwiftStdlib.cmake 可以看到, Swift 没有在 Android 上创造一套自己的 log 系统,它直接链接了 Android 的 Native 的日志 log 来实现,从而支持 Android Studio 的 Logcat :



所以基于 LLVM 的 Android NDK 是实现 Swift 跨平台编译的关键,它让 Swift 编译器能够被“重定向”,从而为 Android 支持的 CPU 架构(如 aarch64armv7x86_64)生成相应的原生机器码 。


$ NDK_PATH=path/to/android-ndk-r27c
$ SWIFT_PATH=path/to/swift-DEVELOPMENT-SNAPSHOT-2024-11-09-a-ubuntu22.04/usr/bin
$ git checkout swift-DEVELOPMENT-SNAPSHOT-2024-11-09-a
$ utils/build-script \
-R \ # Build in ReleaseAssert mode.
--android \ # Build for Android.
--android-ndk $NDK_PATH \ # Path to an Android NDK.
--android-arch aarch64 \ # Optionally specify Android architecture, alternately armv7 or x86_64
--android-api-level 21 \ # The Android API level to target. Swift only supports 21 or greater.
--stdlib-deployment-targets=android-aarch64 \ # Only cross-compile the stdlib for Android, ie don't build the native stdlib for Linux
--native-swift-tools-path=$SWIFT_PATH \ # Path to your prebuilt Swift compiler
--native-clang-tools-path=$SWIFT_PATH \ # Path to a prebuilt clang compiler, one comes with the Swift toolchain
--build-swift-tools=0 \ # Don't build the Swift compiler and other host tools
--build-llvm=0 \ # Don't build the LLVM libraries, but generate some CMake files needed by the Swift stdlib build
--skip-build-cmark # Don't build the CommonMark library that's only needed by the Swift compiler


简而言之,就是编译成 so 。



目前官方要求是在 Linux 环境下(官方推荐 Ubuntu 20.04/22.04)下,使用 Swift 官方提供的交叉编译工具链,将 .swift 源文件编译成原生可执行文件或共享库,之后将编译产物连同必需的 Swift 运行时库,通过 Android adb 推送到 Android 设备或模拟器上,最终这些原生代码可以在 Android 的 shell 环境中直接运行,或被一个标准的 Android 应用加载并调用 :



首先需要运行以下命令复制复制对应的 so :


$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftCore.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftAndroid.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftSwiftOnoneSupport.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswiftRemoteMirror.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswift_Concurrency.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswift_RegexParser.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libswift_StringProcessing.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libdispatch.so /data/local/tmp
$ adb push build/Ninja-ReleaseAssert/swift-linux-x86_64/lib/swift/android/libBlocksRuntime.so /data/local/tmp

然后还需要复制 Android NDK 的 libc++ :


$ adb push /path/to/android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so /data/local/tmp

此外还需要复制在上一步中构建的 hello 可执行文件:


$ adb push hello /data/local/tmp

最终通过 adb shell 命令在 Android 设备上执行 hello 可执行文件:


$ adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/hello

而对于 Android 端来看,此时的 Swift 产物与 C/C++ 代码没什么区别,它必须作为一个标准的 .so 库被加载,并通过 JNI 规范暴露需要支持的能力。


目前 Swift 的核心标准库(stdlib)已经可以成功在 Android 平台进行编译 ,也就是目前 StringIntArrayDictionary 等基础数据类型已经完成基本支持:



更高层次的核心库,比如 FoundationURLSessionJSONEncoder )和 Dispatch(提供并发支持),也正在被移植到 Android 平台。


而对于 UI 部分,目前 Swift 官方暂未提供任何支持 Android 的 UI 框架 ,官方文档目前表示:“You'd need some sort of framework to build a user interface for your application, which the Swift stdlib does not provide” 。



所以,从这个层面看,它更像是 KMP 的存在,而如果需要类似 CMP 的支持,那么大概率需要 SwfitUI 的官方适配,毕竟 Skip 其实只是一个翻译框架。


而在互操作上,其实过去就有 swift-java 这个图的互操作方向的尝试,当时的目标是实现 Swift 与 Java 之间的双向互操作性,即支持 Swift 调用 Java 库,也支持 Java 调用 Swift 库 :



但是从官方描述来看, Swift on Android 似乎并没有直接使用类似桥接绑定,也就是你需要自己实现这部分,如果你需要的话:



而对于 Swift on Android 来说,要让一个 Swift 函数能被外部的 C 代码(以及遵循 C 调用约定的 JNI)所发现和调用,一般也就是通过 @_cdecl 属性,这个属性可以将函数编译成一个简单的、符合 C 语言标准的符号(Symbol)并暴露出去。



虽然没找到对应的 demo 或者实现,但是理论上如果想要不暴露接口,大概率还是通过 @_cdecl



所以目前 Swift on Android 给人的感觉确实很毛坯,在交互和 UI 上都很欠缺,看起来只是开源了一种可能,具体能达到什么效果暂时还看不出来,但是多少算是官方起了个头,也算是有了希望,对于 iOS 来说,这个春天还需要再等等。


那么,你觉得 Swift on Android 的存在多久可以达到生产标准?


参考链接



作者:恋猫de小郭
来源:juejin.cn/post/7520063683180199999
收起阅读 »

不负责任观察:程序员哪个年龄段最卷?

前言 最近有看到两个报告,调查、总结、2024年程序员的生存情况以及一些工作情况,国内国外都有。接下来摘抄部分数据看看是否与我们的实际相符。 1. 程序员的年龄分段 先看国内的数据: 可以看出,2630岁之间的程序员占比是最多的,1835岁之间占比将近80%...
继续阅读 »

前言


最近有看到两个报告,调查、总结、2024年程序员的生存情况以及一些工作情况,国内国外都有。接下来摘抄部分数据看看是否与我们的实际相符。


1. 程序员的年龄分段


先看国内的数据:


image.png


可以看出,2630岁之间的程序员占比是最多的,1835岁之间占比将近80%。
18~25岁,包含在校学生和刚毕业三年内的学生,按现在考研的趋势,这部分占比会逐渐变低。
35岁以上占比接近19%,说明还是有不少大龄程序员。


再看国外的数据:
image.png


2124岁、2529岁占比是并列第一,18~35岁之间占比将近70%。
35岁以上占比30%,说明国外程序员"老龄化"更严重。


看国家之间的对比:


18~29岁程序员分布的国家。


image.png


论哪里拥有最多的年轻程序员?还得是神秘的东方大国,人口大国、文明古国---印度。怪不得印度程序员在美国混得很开,毕竟每年都有大量的年轻程序员。
中国在中东、非洲、中亚之后。
看样子美国有不少大龄程序员。


2. 程序员的工作年限


先看国内的数据:


image.png


工作13年是最多的,其次是310年。
而10年以上的就比较少,这个时间大都32岁以上了,中途有不少人主动、被动转行。


再看国外的数据:


image.png


拥有3~5年的工作经历占比最多,10年以上的工作经历占比接近30%,这比国内的高。


3. 程序员的薪资水平


先看国内水平:


image.png


大部分月收入是在10k20k之间,换算成年收入在12w24w之间。
这和地域有关系,比如一个程序员在一线城市北上深薪资20k,那么到二线城市如杭州、成都、武汉可能会打七折,如果再到长沙、西安等估计还会更低。


再看国外水平(收入中位数):
image.png


此处显示的是年薪,可以看到美国程序员的收入遥遥领先。
按照汇率计算:


image.png


image.png
美国程序员收入中位数是百万年薪(人民币)。
而中国是22万人民币,此处的差距还是比较大,同志仍需努力。


4. 哪个年龄段最卷?


通过上述数据,可以看出,35岁以下程序员群体最庞大,工作十年以内人数最多,工资10k~20k人最多,这也符合我们平时职场的感知。


22~25岁,刚毕业几年,正是学习知识,刷小怪升级的时候,按理来说应该会在下班时间蹭公司的免费空调自我学习提升。然而,经过实际观察,目前这个年龄段是00后占据主体,大部分是到点下班。
访谈得知原因如下:




  1. 大学四年大部分在上网课,天天对着电脑,现在工作还是对着电脑,顶不住,下班就直接溜。

  2. 我加班能得到什么?就这点钱只能买我8小时。

  3. 老员工都是既得利益者,是公司的"精神股东",我们就是喽啰,不做额外奉献。



25~30岁,已经在职场中历练了不少年,写的bug、产生的线上事故、输出的复盘文档、与其它部门撕逼等等统统都有经验了,理论上来应该不怎么卷,而实际上最卷的反而是这段年龄的。
总结原因如下:




  1. 实战经验积累了不少,成为技术骨干,需要调研、学习的东西更多了;平时开会撕逼、晚上怒写业务、周末学习新知识提升自我,花费的时间比较多。

  2. 这个年龄段处在恋爱、结婚的思考期,没有家庭、小孩的牵挂,留给自己的时间更多。

  3. 有些还独挡一面当了leader,比如前端小组长,还想再往上踮踮脚,够一下,博一下,卷的主观能动性比较强。



30~35岁,职场老油条,见多识广,动态卷,就是比较能苟。
交流总结如下:




  1. 家庭牵扯了不少精力,还好靠经验能弥补一些亏空。

  2. 发展的天花板已经看到,就是摸不着,不相信什么大器晚成,看不到太多希望,做好自己分内事就好。

  3. 每年的体检总是新增各项小毛病,更加关注自己的身体健康。

  4. 懂得职场潜规则,该加班配合的演出还是不能视而不见。



35~45岁,这个年龄段出任CEO、赢取白富美的凤毛麟角,要么上升,要么转行,留下来继续编码的反而是最看开的一群人,因为身体/精神原因,没实力卷,实在卷不动。
访谈如下:




  1. 我在外包挺好的,再干个几年存够社保和养老金就退休。

  2. 不争不吵,你说的都对,按你的来。

  3. 组内都是年少有为的人啊,天赋高又刻苦,公司的发展靠你们了,我的养老也靠你们了。

  4. 最近又发现了个野钓的地方,不容易空军,周末赶早去来一杆。



45岁以上,职场除了高管,没见过这个年龄段的一线码农。
按现在发展,也许多年后,我会看见这样的自己。


作者:小鱼人爱编程
来源:juejin.cn/post/7520085904339173430
收起阅读 »

国产大模型高考出分了:裸分 683,选清华还是北大?

这两天啊,各地高考的成绩终于是陆续公布了。 现在,也是时候揭晓全球第一梯队的大模型们的 “高考成绩” 了—— 我们先来看下整体的情况(该测试由字节跳动 Seed 团队官方发布): 按照传统文理分科计分方式,Gemini 的理科总成绩 655 分,在所有选手里...
继续阅读 »

这两天啊,各地高考的成绩终于是陆续公布了。


现在,也是时候揭晓全球第一梯队的大模型们的 “高考成绩” 了——


我们先来看下整体的情况(该测试由字节跳动 Seed 团队官方发布):



按照传统文理分科计分方式,Gemini 的理科总成绩 655 分,在所有选手里排名第一。豆包的文科总成绩 683 分,排名第一,理科总成绩是 648 分,排名第二。


再来看下各个细分科目的成绩情况:



除了数学、化学和生物之外,豆包的成绩依旧是名列前茅,6 个科目均是第一。


不过其它 AI 选手的表现也是比较不错,可以说是达到了优秀学生的水准。


比较遗憾的选手就要属 O3,因为它在语文写作上跑了题,因此语文成绩仅 95 分,拉低了整体的分数。


若是从填报志愿角度来看,因为这套测试采用的是山东省的试卷,根据过往经验判断,3 门自选科目的赋分相比原始分会有一定程度的提高,尤其是在化学、物理等难度较大的科目上。本次除化学成绩相对稍低外,豆包的其余科目组合的赋分成绩最高能超过 690 分,有望冲刺清华、北大。


(赋分规则:将考生选考科目的原始成绩按照一定比例划分等级,然后将等级转换为等级分计入高考总分)


好,那现在的豆包面临的抉择是:上清华还是上北大?



大模型参加高考,分数怎么判?


在看完成绩之后,或许很多小伙伴都有疑惑,这个评测成绩到底是怎么来的。


别急,我们这就对评测标准逐条解析。


首先在卷子的选择上,由于目前网络流出的高考真题都是非官方的,而山东是少数传出全套考卷的高考大省;因此主科(即语文、数学、英语)采用的是今年的全国一卷,副科采用的则是山东卷,满分共计 750 分。


其次在评测方式上,都是通过 API 测试,不会联网查询,评分过程也是参考高考判卷方式,就是为了检验模型自身的泛化能力:



  • 选择题、填空题


    采用机评(自动评估)加人工质检的方式;


  • 开放题


    实行双评制,由两位具有联考阅卷经验的重点高中教师匿名评阅,并设置多轮质检环节。



在给模型打分的时候,采用的是 “3 门主科(语文数学英语)+3 门综合科(理综或文综)” 的总分计算方式,给五个模型排了个名次。


值得一提的是,整个评测过程中,模型们并没有用任何提示词优化技巧来提高模型的表现,例如要求某个模型回答得更详细一些,或者刻意说明是高考等等。


最后,就是在这样一个公平公正的环境之下,从刚才我们展示的结果来看,Gemini、豆包相对其他 AI 来说取得了较优的成绩。


细分科目表现分析


了解完评测标准之后,我们继续深入解读一下 AI 选手们在各个科目上的表现。


由于深度思考的大火,大模型们在数学这样强推理科目上的能力明显要比去年好很多(此前大部分均不及格),基本上都能达到 140 分的成绩。


不过在一道不算难的单选题(全国一卷第 6 题)上,国内外的大模型们却都栽了跟头:



这道题大模型们给出的答案是这样的:


豆包:C;Gemini:B;Claude:C;O3:C;DeepSeek:C


但这道题的正解应该是 A,因此大模型们在此全军覆没。


之所如此,主要是因为题目里有方框、虚线、箭头和汉字混在一起的图,模型认不准图像,说明它们在 “看图说话” 这块还有进步空间。


以及在更难的压轴大题上,很多大模型也没完全拿下,经常漏写证明过程,或者推导不严谨被扣分,说明在细节上还需加强。


到做语文选择题和阅读题这两个版块,大模型们几乎是 “学霸本霸”,得分率超高。


不过在作文写作过程也暴露出了一些问题,例如写作过于刻板、文字冰冷,文章字数不达标(不足 800 字或超过 1200 字)、立意不对,形式上还经常会出现惯用的小标题。



在英语测试过程中,大模型们几乎挑不出毛病,唯一扣分点是在写作上,比如用词不够精准、句式稍显单调,但整体已经很接近完美。


对于理综,遇到带图的题目大模型们还是会犯难,不过豆包和 Gemini 这俩模型在看图像和理解图的能力上会比其他模型强一些。


例如下面这道题中,正确答案应当是 C,大模型们的作答是这样的:


豆包:C;Gemini:C;Claude:D;O3:D;DeepSeek:D



最后在文综方面,大模型的地域差别就显现得比较明显,国外的大模型做政治、历史题时,经常搞不懂题目在考啥,对中国的知识点不太 “感冒”。


而对于地理题,最头疼的便是分析统计图和地形图,得从图里精准提取信息再分析。


以上就是对于本次评测的全面分析了。


除了今年国内的高考之外,这几位 “参赛选手” 还参加了印度理工学院的第二阶段入学考试——JEE Advanced


这场考试每年有数百万人参与第一阶段考试,其中前 25 万考生可晋级第二阶段。它分为两场,每场时长 3 小时,同时对数学、物理、化学三科进行考察。


题目以图片形式呈现,重点考查模型的多模态处理能力与推理泛化能力。所有题目均为客观题,每道题进行 5 次采样,并严格按照 JEE 考试规则评分——答对得分、答错扣分,不涉及格式评分标准。


与全印度人类考生成绩对比显示,第一名得分 332 分,第十名得分 317 分。


值得注意的是,豆包与 Gemini 已具备进入全印度前 10 的实力:Gemini 在物理和化学科目中表现突出,而豆包在数学科目 5 次采样中实现全对。



怎么做到的?


相比去年一本线上下的水平,整体来看,大模型们在今年高考题上的表现均有明显的进步。


那么它们到底是如何提升能力的?我们不妨以拿下单科第一最多的豆包为例来了解一下。


豆包大模型 1.6 系列,是字节跳动 Seed 团队推出的兼具多模态能力与深度推理的新一代通用模型。


团队让它能力提升的技术亮点,我们可以归结为三招。


第一招:多模态融合与 256K 长上下文能力构建


Seed1.6 延续了 Seed1.5 在稀疏 MoE(混合专家模型)领域的技术积累,采用 23B 激活参数与 230B 总参数规模进行预训练。其预训练过程通过三个阶段实现多模态能力融合与长上下文支持:



  • 第一阶段:纯文本预训练

    以网页、书籍、论文、代码等数据为训练基础,通过规则与模型结合的数据清洗、过滤、去重及采样策略,提升数据质量与知识密度。

  • 第二阶段:多模态混合持续训练(MMCT)

    进一步强化文本数据的知识与推理密度,增加学科、代码、推理类数据占比,同时引入视觉模态数据,与高质量文本混合训练。

  • 第三阶段:长上下文持续训练(LongCT)

    通过不同长度的长文数据逐步扩展模型序列长度,将最大支持长度从 32K 提升至 256K。


通过模型架构、训练算法及 Infra 的持续优化,Seed1.6 base 模型在参数量规模接近的情况下,性能较 Seed1.5 base 实现显著提升,为后续后训练工作奠定基础。


这一招的发力,就对诸如高考语文阅读理解、英语完形填空和理科综合应用题等的作答上起到了提高准确率的作用,因为它们往往涉及长文本且看重上下文理解。


第二招:多模态融合的深度思考能力


Seed1.6-Thinking 延续 Seed1.5-Thinking 的多阶段 RFT(强化反馈训练)与 RL(强化学习)迭代优化方法,每轮 RL 以上一轮 RFT 为起点,通过多维度奖励模型筛选最优回答。相较于前代,其升级点包括:



  • 拓展训练算力,扩大高质量数据规模(涵盖 Math、Code、Puzzle 等领域);

  • 提升复杂问题的思考长度,深度融合 VLM 能力,赋予模型清晰的视觉理解能力;

  • 引入 parallel decoding 技术,无需额外训练即可扩展模型能力 —— 例如在高难度测试集 Beyond AIME 中,推理成绩提升 8 分,代码任务表现也显著优化。


这种能力直接对应高考中涉及图表、公式的题目,如数学几何证明、物理电路图分析、地理等高线判读等;可以快速定位关键参数并推导出解题路径,避免因单一模态信息缺失导致的误判。


第三招:AutoCoT 解决过度思考问题


深度思考依赖 Long CoT(长思维链)增强推理能力,但易导致 “过度思考”—— 生成大量无效 token,增加推理负担。


为此,Seed1.6-AutoCoT 提出 “动态思考能力”,提供全思考、不思考、自适应思考三种模式,并通过 RL 训练中引入新奖励函数(惩罚过度思考、奖励恰当思考),实现 CoT 长度的动态压缩。


在实际测试中:



  • 中等难度任务(如 MMLU、MMLU pro)中,CoT 触发率与任务难度正相关(MMLU 触发率 37%,MMLU pro 触发率 70%);

  • 复杂任务(如 AIME)中,CoT 触发率达 100%,效果与 Seed1.6-FullCoT 相当,验证了自适应思考对 Long CoT 推理优势的保留。


以上就是豆包能够在今年高考全科目评测中脱颖而出的原因了。


不过除此之外,还有一些影响因素值得说道说道。


正如我们刚才提到的,化学和生物的题目中读图题占比较大,但因非官方发布的图片清晰度不足,会导致多数大模型的表现不佳;不过 Gemini2.5-Pro-0605 的多模态能力较突出,尤其在化学领域。


不过最近,字节 Seed 团队在使用了更清晰的高考真题图片后,以图文结合的方式重新测试了对图片理解要求较高的生物和化学科目,结果显示 Seed1.6-Thinking 的总分提升了近 30 分(理科总分达 676)。



这说明,全模态推理(结合文本与图像)能显著释放模型潜力,是未来值得深入探索的方向。


那么你对于这次大模型们的 battle 结果有何看法?欢迎大家拿真题去实测后,在评论区留言你的感受~


评分明细详情:

bytedance.sg.larkoffice.com/sheets/QgoF…


欢迎在评论区留下你的想法!


—  —


作者:量子位
来源:juejin.cn/post/7519891830894034959
收起阅读 »

前端与Brain.js融合的未来

AI 端模型与前端开发的新时代 随着技术的发展,人工智能(AI)正以前所未有的速度融入我们的生活。从前端到后端,从移动应用到物联网设备,AI的应用场景越来越广泛。特别是在前端领域,AI技术的引入为网页开发带来了前所未有的机遇。 什么是脑神经网络库(Brain....
继续阅读 »

AI 端模型与前端开发的新时代


随着技术的发展,人工智能(AI)正以前所未有的速度融入我们的生活。从前端到后端,从移动应用到物联网设备,AI的应用场景越来越广泛。特别是在前端领域,AI技术的引入为网页开发带来了前所未有的机遇。


什么是脑神经网络库(Brain.js)


在前端领域,Brain.js 是一个非常受欢迎的库,它允许开发者在浏览器中直接使用神经网络进行各种任务,如文本分类、图像识别等。Brain.js 的一大优势在于其易于上手,即使是没有深厚机器学习背景的开发者也能快速开始使用。


Brain.js 在前端开发中的应用


数据准备

首先,我们需要准备用于训练神经网络的数据。这些数据通常以JSON数组的形式存在,每个元素包含输入(input)和输出(output)。例如,在以下示例中,我们准备了一组关于前端和后端开发的知识点,用于训练一个能够区分两者差异的神经网络。


const data = [
{ "input": "implementing a caching mechanism improves performance", "output": "backend" },
// 更多数据...
];

神经网络初始化

接下来,我们使用 brain.recurrent.LSTM() 函数初始化一个长短期记忆(LSTM)神经网络。LSTM是一种特殊的递归神经网络(RNN),特别适合处理序列数据,如文本或时间序列。


const network = new brain.recurrent.LSTM();

模型训练

有了数据和神经网络之后,我们就可以开始训练模型了。训练过程可能需要一些时间,具体取决于数据集的大小和复杂度。network.train() 方法接受数据集作为参数,并允许设置训练的迭代次数和其他选项。


network.train(data, {
iterations: 2000, // 迭代次数
log: true, // 是否打印训练日志
logPeriod: 100 // 日志打印频率
});

应用模型

一旦模型训练完成,我们就可以使用 network.run() 方法对新的输入进行预测。例如,我们可以测试模型是否能正确地将“使用Flexbox布局”归类为前端开发。


const output = network.run("using flexbox for layout");
console.log(output); // 输出结果

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI 端模型- 前端开发的时代</title>
</head>
<body>
<script src="./brain.js"></script>
<script>
// json 数组
// 输入 input
// 喂给大模型的数据
const data = [
{ "input": "implementing a caching mechanism improves performance", "output": "backend" },
{ "input": "hover effects on buttons", "output": "frontend" },
{ "input": "optimizing SQL queries", "output": "backend" },
{ "input": "using flexbox for layout", "output": "frontend" },
{ "input": "setting up a CI/CD pipeline", "output": "backend" },
{ "input": "SVG animations for interactive graphics", "output": "frontend" },
{ "input": "authentication using OAuth", "output": "backend" },
{ "input": "responsive images for different screen sizes", "output": "frontend" },
{ "input": "creating REST API endpoints", "output": "backend" },
{ "input": "CSS grid for complex layouts", "output": "frontend" },
{ "input": "database normalization for efficiency", "output": "backend" },
{ "input": "custom form validation", "output": "frontend" },
{ "input": "implementing web sockets for real-time communication", "output": "backend" },
{ "input": "parallax scrolling effect", "output": "frontend" },
{ "input": "securely storing user passwords", "output": "backend" },
{ "input": "creating a theme switcher (dark/light mode)", "output": "frontend" },
{ "input": "load balancing for high traffic", "output": "backend" },
{ "input": "accessibility features for disabled users", "output": "frontend" },
{ "input": "scalable architecture for growing user base", "output": "backend" }
];
// 初始化一个神经网络
const network = new brain.recurrent.LSTM();
// 训练 花蛮长时间
network.train(data,{
iterations: 2000,
log:true,
logPeriod:100
});
// 执行一下
const output = network.run("using flexbox for layout");
console.log(output);
</script>
</body>
</html>

前端与AI融合的未来


随着技术的进步,AI在前端的应用将更加广泛。从智能表单验证到个性化推荐系统,从前端性能优化到用户界面的自动设计,AI技术为前端开发提供了无限的可能性。此外,随着端侧模型(如AGI端侧模型)的发展,未来的设备将变得更加智能,能够即时响应用户的需要,提供更加个性化的体验。


最后,AI与前端开发的结合不仅提升了用户体验,也为开发者带来了新的挑战和机遇。通过不断学习和探索,我们能够在这个充满活力的领域中创造出更多令人兴奋的作品。




作者:Danta
来源:juejin.cn/post/7441116826623393829
收起阅读 »

从 DeepSeek 看25年前端的一个小趋势

大家好,我卡颂,专注于AI助力程序员转型(阅读我的更多思考) 最近DeepSeek R1爆火。有多火呢?连我爷爷都用上了,还研究起提示词工程来了。 大模型不断发展对我们前端工程师有什么长远影响呢?本文聊聊25年前端会有的一个小趋势。 模型进步的影响 像Deep...
继续阅读 »

大家好,我卡颂,专注于AI助力程序员转型阅读我的更多思考


最近DeepSeek R1爆火。有多火呢?连我爷爷都用上了,还研究起提示词工程来了。


大模型不断发展对我们前端工程师有什么长远影响呢?本文聊聊25年前端会有的一个小趋势。


模型进步的影响


DeepSeek R1这样的推理模型和一般语言模型(类似Claude SonnetGPT-4oDeepSeek-V3)有什么区别呢?


简单来说,推理模型的特点是:推理能力强,但速度慢、消耗高


他比较适合的场景比如:



  • Meta Prompting(让推理模型生成或修改给一般语言模型用的提示词

  • 路径规划


等等


这些应用场景主要利好AI Agent


再加上一般语言模型在生成效果、token上下文长度上持续提升。可以预见,类似Cursor Composer Agent这样的AI Agent在25年能力会持续提升,直到成为开发标配。


这会给前端工程师带来什么进一步影响呢?


一种抽象的理解


我们可以将AI Agent抽象得理解为应用压缩算法,什么意思呢?


Cursor Composer Agent举例:



我们传入:



  • 描述应用状态的提示词

  • 描述应用结构的应用截图


AI Agent帮我们生成应用代码。



同样,也能反过来,让AI Agent根据应用代码帮我们生成描述应用的提示词



从左到右可以看作是解压算法,从右往左可以看作是压缩算法


就像图片的压缩算法存在失真,基于AI Agent抽象的应用压缩算法也存在失真,也就是生成的效果不理想


随着上文提到的AI Agent能力提高(背后是模型能力提高、工程化的完善),应用压缩算法的失真率会越来越低。


这会带来什么进一步的影响呢?


对开发的影响


如果提示词(经过AI Agent)就能准确表达想要的代码效果,那会有越来越多原本需要用代码表达的东西被用提示词表达。


比如,21st.dev的组件不是通过npm,而是通过提示词引入。


相当于将引入组件的流程从:开发者 -> 代码


变成了:开发者 -> 提示词 -> AI Agent -> 代码



再比如,CopyCoder是一款上传应用截图,自动生成应用提示词的应用。


当你上传应用截图后,他会为你生成多个提示词文件。


其中.setup描述AI Agent需要执行的步骤,其他文件是描述应用实现细节的结构化提示词



这个过程相当于根据应用截图,将应用压缩为提示词


很自然的,反过来我们就能用AI Agent将这段提示词重新解压为应用代码。


这个过程在25年会越来越丝滑。


这会造成的进一步影响是:越来越多前端开发场景会被提炼为标准化的提示词,比如:



  • 后台管理系统

  • 官网

  • 活动页


前端开发的日常编码工作会越来越多被上述流程取代。


你可能会说,当前AI生成的代码效果还不是很好。


但请注意,我们谈的是趋势。当你日复一日做着同样的业务时,你的硅基对手正在每年大跨步进步。


总结


随着基础模型能力提高,以及工程化完善,AI Agent在25年会逐渐成为开发标配。


作为应用开发者(而不是算法工程师),我们可以将AI Agent抽象得理解为应用压缩算法


随着时间推移,这套压缩算法的失真率会越来越低。


届时,会有越来越多原本需要用代码表达的东西被用提示词表达。


这对前端工程师来说,既是机遇也是挑战。


作者:魔术师卡颂
来源:juejin.cn/post/7468323178931879972
收起阅读 »

体验了无业一年和远程工作一个月, 你猜有想象中那么爽吗

失业了一年多后, 有了一个特殊的契机, 远程工作到现在一个月了, 有很多感触想聊一下. 在家工作有想象中那么爽吗? 爽, 但一些情况与想象中的并不一样. 不用上下班真的节约时间吗? 真的, 而且节约的不只是上下班的时间. 还有穿衣服, 理书包, 下楼, 上楼,...
继续阅读 »

失业了一年多后, 有了一个特殊的契机, 远程工作到现在一个月了, 有很多感触想聊一下.


在家工作有想象中那么爽吗?


爽, 但一些情况与想象中的并不一样.


不用上下班真的节约时间吗?


真的, 而且节约的不只是上下班的时间.


还有穿衣服, 理书包, 下楼, 上楼, 到了公司里先休息下, 和"等待"的时间.


这些时间其实是非常长的, 特别是一些"等待"时间, 比如打算8:40出门, 但准备好一切后是8:20, 人就会自动进入发呆时间. 也许上班路程就40分钟, "等待"就浪费20分钟了.


在家工作, 电脑就在床头, 拿起电脑就开干, 热启动, 非常节省时间.


在家工作可以兼顾陪伴家人吗?


完全不可以.


在真正工作的状态, 家里人跟我说话, 我都是木头状态.


并且在工作不那么紧急的时候, 我还要花额外的精力来拒绝家人的交互 (因为不好意思直接拒绝), 这点上, 在家工作对我来说是缺点的.


在家里有紧急事情的情况下, 在家工作是好的, 但我现在的状态是不需要的.


在一些需要跨部门交流的事情上, 还是在公司里, 拿着电脑去别人工位盯着效率会高很多.


不干活一年多爽不爽?


爽, 懒惰的爽, 很多情况与想象的完全不同.


不用干这些业务有更多时间学习?


只多了一点时间.


如果具体举例, 假设工作时: 工作6小时, 学习2小时. 失业时: 刷手机5小时, 学习3小时.


而我本以为可能是学习6小时, 娱乐2小时.


因为家里有小孩, 我会去图书馆学习, 大概是12点去, 最多3点就忍不住回家了.


不工作起床也要晚2~3小时.


反而在上班的时候, "不能干别的, 但工作做完了", 是最佳的学习状态.


(更别说弹琴了, 真是可笑, 本以为可以有时间弹琴了)


不上班可以到处玩了?


是的. 非常爽.


并且可以吃很多"工作日专享", 比如我吃了好多次 90 快的一绪寿喜烧.


刚失业买了新的摩托车, 出去玩了很多次.


虽然也有疲倦期, 但是恢复很快.


如果不是小孩子和家里事情的关系, 我可能会去很远的地方.


不上班很开心吗?


认真思考后, 我认为分为2个方面.


第一是钱的方面. 长期没工作可能导致从行业除名. 这样算会失去的钱是非常多的, 会导致焦虑.


第二是成就感. 在工作和学习中, 在解决了麻烦的问题后是有成就感的, 而失业的状态几乎就是慵懒.


抛开长期不谈, 这种状态的快乐上限是比工作底的.


这是很客观的说了"不上班的缺点".


而结合这2个缺点, 与一些优点(可以出去玩, 可以陪伴家人)后. 结论还是非常复杂的.


但总的来说, 还是想有个逼班上的.


现状和未来的几个月


现状


现在的工作是单人负责一个前端项目, 责任清晰, 干完活也没别的可干, 做得好坏大家都知道是我.


我认为是个很好的感觉, "一个和尚挑水喝".


虽然我是随时工作的状态, 睡醒拿起旁边的电脑就干, 但是没觉得不开心.


和以前公司那种分散责任状态不同.


公司里即使是一人一项目, 空的时候也会被借到其他组, 是真的很搓.


我把活干完, 就是自己的时间. 当然, 不小的概率是失去这份短工.


人的状态


这里要插入下自己的感受.


觉得"人的状态"很神奇, 就是工作了, 在没有任何痛苦的情况下, 人的行为改变非常大.


因为我的骨折和工作, 周围人的行为改变也非常大, 本来"做不来"的事, 都可以做了.


自己都不能理解自己的另一个状态, 更何况他人, 所以不要评价任何他人的行为了吧.


如果觉得自己做事情都很难, 可以尝试给自己找机会换个状态.


心理准备


其实是很开心的工作, 但合同里只要3天通知我, 我就可以失业了.


因为找了一年工作, 知道找工作的艰难. 所以对待这次工作的每个事情, 我都是很认真的.


很忙的一个月过去, 200多个commit, 解决了80多个jira.


其中也记录了一些麻烦的问题, 是 react 的, 会根据后面的生活状态, 总结一下.


作者:nujnewnehc
来源:juejin.cn/post/7498968249548554266
收起阅读 »

低代码是“未来”还是“骗局”?作为前端我被内耗到了

「我一个前端,最后成了平台数据填表员,写页面?不存在的。」 😅项目开始前,我是兴奋的 当领导说“这个项目我们用低代码平台做,提效百分百”,我甚至有点激动。 作为一个写了 5 年组件的前端老油子,谁不想脱离日复一日的 v-model 和 props 地狱? 领...
继续阅读 »

「我一个前端,最后成了平台数据填表员,写页面?不存在的。」



😅项目开始前,我是兴奋的


当领导说“这个项目我们用低代码平台做,提效百分百”,我甚至有点激动。


作为一个写了 5 年组件的前端老油子,谁不想脱离日复一日的 v-modelprops 地狱?


领导还补充:“平台我们组自己封装的,配个 schema 就能跑,前端工程师只需要写逻辑。”


我一听这话,心想:



终于要进入“写配置赚钱”的时代了!



然而,我万万没想到——这段低代码旅程,最后让我怀疑人生。




😵上线第一天,我差点把键盘砸了


第一个需求很简单:



做个带搜索、分页、导出 Excel 的用户列表页。



我打开平台,选择“表格组件”,拖入“搜索框”,配置字段、绑定接口——一切都看起来毫无门槛。


结果运行之后,搜索没反应、分页错乱、导出根本没绑定。


我一查 schema,300 多行配置里,居然混了三种不同的写法:


{
"onSearch": "handleSearch",
"onSearch()": "handleSearch",
"onSearchEvent": "handleSearch"
}

问后端:“你这个文档是哪个是对的?”


后端说:“都对,我们兼容了。”


我瞬间明白:这不是低代码,这是自制混沌生成器。




🤯技术债太多,修个 key,整页全崩


最魔幻的一次,是我想修改表格的一个字段名,从 user_name 改成 username


我只是改了 schema 的字段名,结果:



  • 表格没显示

  • 搜索没了

  • 编辑表单也报错

  • 提交接口直接抛了个 500


我调试了三个小时,才发现平台内部是按字段名 字符串拼接 key 绑定状态 的……只要字段名变了,所有逻辑都得重配。


我恍然大悟:



传统开发用 IDE 报错提醒你;低代码等你点击线上按钮才告诉你挂了。





😓协作地狱:产品配页面,我修 schema


最痛苦的不是技术问题,而是人。


产品说:“我来拖页面,你只用帮我看看为什么点了没反应。”


然后我收到一个 schema 文件,2000 行,不带注释,结构是这样:


{
"component": "Form",
"props": {
"items": [
{
"label": "名称",
"field": "formA.formB.userName",
"rules": "{ required: true }",
"props": {
"onClick": "fn1()"
}
}
]
}
}

我想问三件事:



  1. 你这个路径到底是怎么拼出来的?

  2. 为什么校验规则是字符串?

  3. 你拖了个按钮怎么会触发五个请求?


我调试一天,结论是:产品误操作删除了一个容器组件,但平台没报错,直接让数据结构断链。




🧨所谓低代码:把逻辑封死、把锅甩你


我总结这个项目两个最深的坑:


1. 复杂交互,低代码写不来


比如“用户选择类型后,自动拉接口重新加载选项”这种需求,纯配置根本搞不定。


最后我只能写自定义组件注入到平台里,甚至还要写类似:


platform.on("fieldChange", (field, value) => {
if (field === "type") {
reloadOptions(value)
}
})

这叫低代码吗?我写的代码比原来还绕。


2. 前端不是没活了,是变成了“修配置+查日志工程师”



  • 页面功能跑飞了?前端看 schema;

  • 按钮不响应?前端查绑定字段;

  • 接口返回异常?前端加拦截 hook;

  • 表单校验失败?前端写正则规则;


最后我只写了两行 JS,却维护了十几套 JSON。


我真的开始怀疑,前端的价值,是不是变成了“修别人的 schema”?




🧩我从这个项目学到的东西


不是说低代码没用,而是:



不是所有团队都配拥有一套低代码平台。



低代码系统真正的“提效”,需要这些前提:



  1. 强约束的规范体系(字段、组件、交互都必须有标准)

  2. 良好的权限隔离机制(避免“产品能改逻辑,运营能删字段”)

  3. 持续有人维护平台底层能力(不然技术债只会越来越重)

  4. 合理的分工协作机制(schema 的维护不应该是前端一个人干)


否则,它只是一个混乱责任分配工具,表面上 everyone can build,实际上 everyone push bugs。




📌低代码,不是骗局,也不是未来——是一个选项


如果你问我现在怎么看低代码?


我的回答是:



低代码不是“未来”也不是“骗局”,而是“项目管理方式的折中”。



它适合一些场景:



  • 表单多、CRUD 重复度高的后台系统;

  • 业务快速试错、页面变动频繁的 MVP 阶段;

  • 运营自己想搭点落地页的场景。


但如果你希望:



  • 页面复杂,交互灵活;

  • 可测试、可维护、可拓展;

  • 高性能、大工程;


那——你得写代码。




🗣最后


你也踩过低代码的坑吗?
有没有类似“debug 三小时发现产品配错 schema”的经历?


📌 你可以继续看我的《为什么》系列文章



作者:ErpanOmer
来源:juejin.cn/post/7514611888991387667
收起阅读 »

前端难还是后端难?作为八年后端开发,我想说点实话

前端难还是后端难?作为八年后端开发,我想说点实话 前端容易吗?不容易。 后端轻松吗?也不轻松。 那到底哪个更难? 这事还真不是一句话能说清楚的…… 一、先说说我个人的背景 我是一个写了 8 年 Java 后端的程序员,经历过中后台系统、金融系统、ToC ...
继续阅读 »

前端难还是后端难?作为八年后端开发,我想说点实话



前端容易吗?不容易。

后端轻松吗?也不轻松。

那到底哪个更难?

这事还真不是一句话能说清楚的……





一、先说说我个人的背景


我是一个写了 8 年 Java 后端的程序员,经历过中后台系统、金融系统、ToC App 的服务端架构,也跟前端打了无数交道。从最早的 jQuery 到现在的 Vue、React、Vite,从最早的 JSP 页面到现在的前后端分离,我见证了不少“变化”。


我不是要拉踩谁,只是想以一个偏后端开发者的视角,聊聊我对“前端难还是后端难”这个话题的理解。




二、前端的“难”是不断变化的“浪潮”


不得不承认,前端的变化速度是真的快。去年刚学完 Vue 2,今年要学 Vue 3;React 的 Hook 还没深入掌握,新的 Server Component 又来了;Webpack 配熟了,Vite 火了;CSS 还没写顺手,Tailwind 席卷而来。


除了框架和工具链的变化,更别说适配各种浏览器、屏幕尺寸、终端设备、无障碍要求、多语言、性能优化、SEO、交互设计……


而且最近几年,前端逐渐“全栈化”:你可能要写服务端渲染(SSR)、搞 Node 服务、上 Docker 部署、调数据库、甚至自己写接口 mock。


前端难吗?难,而且是越来越难。




三、后端的“难”是看不见的深度


后端的难,往往藏在系统的底层逻辑中。你可能看不到一个后端接口的“UI 效果”,但它背后往往涉及:



  • 数据库设计 & 索引优化

  • 分布式事务

  • 消息队列 & 异步处理

  • 缓存策略 & 数据一致性

  • 服务容灾 & 高可用架构

  • 权限系统、加密解密、审计日志

  • 安全防护(SQL 注入、XSS、CSRF)

  • 性能调优 & JVM 调试

  • CI/CD、灰度发布、日志平台接入


而且一旦出问题,前端崩了是“用户体验不好”,后端崩了是“公司赔钱” 。这不是开玩笑,有一次我们一个订单服务接口挂了 5 分钟,损失了几十万。


后端难吗?当然难,而且是“看不见但不能错”的难。




四、我最怕的不是“前端难”或“后端难”,而是互相看不起


说实话,我见过太多前后端互相“看不上”的情况:



  • 后端觉得前端就是摆样子,“你不就封个壳子嘛?”

  • 前端觉得后端接口又臭又长,“你这 JSON 谁看得懂?”

  • 后端吐槽前端不会调接口,前端吐槽后端不会写文档……


但你仔细去看,一个优秀的前端开发,往往比很多“伪全栈”更懂系统结构;一个优秀的后端,也会在意接口的易用性、响应速度和文档清晰度。


技术没有高低,但人有格局。




五、站在“代码人生”的角度看,难易是阶段性的


我年轻的时候觉得后端“更高级”,因为能接触系统底层、数据和业务逻辑。但这几年,我越来越觉得前端也有它独特的价值:



  • 是前端让用户第一眼喜欢上产品;

  • 是前端让复杂的系统变得“看得见”;

  • 是前端在用户和系统之间,搭了一座桥。


你说哪个更重要?没有谁离开谁就能独立运行的系统


我现在更看重的是协作、共建、以及对整个产品的理解。做前端也好,后端也罢,最终我们解决的都是“人”的问题 —— 让人更高效、更便捷、更愉快地使用系统。




六、那到底哪个更难?


如果你非要我选一个答案,我只能说:



哪个你不熟,哪个就难。



前端和后端,都有容易入门但难以精进的曲线。你用 jQuery 写个页面不难,但你做一个大型可维护的组件库就难了;你写个 CRUD 接口不难,但你做一个高并发分布式系统就非常难。


真正的难点在于:你愿不愿意持续去深入、去理解、去完善自己的认知体系。




七、写在最后:别问“哪个难”,问“你想走多远”


我见过写前端写到年薪百万的,也见过写后端写到身心俱疲的。


我见过全栈工程师一人顶两人,也见过只会写“增删改查”却年薪 30w 的老哥。


这行最不缺的,就是例外;最需要的,是清醒的自我认知。


别纠结哪个更难,多花时间让自己变强,才是正解。




**你觉得前端难,还是后端难?你有没有在项目里遇到“前后端合作”的那些故事?欢迎评论区聊聊.


作者:天天摸鱼的java工程师
来源:juejin.cn/post/7516897654170222592
收起阅读 »

进入外包,我犯了所有程序员都会犯的错!

前言 前些天有位小伙伴和我吐槽他在外包工作的经历,语气颇为激动又带着深深的无奈。 本篇以他的视角,进入他的世界,看看这一段短暂而平凡的经历。 1. 上岸折戟尘沙 本人男,安徽马鞍山人士,21年毕业于江苏某末流211,在校期间转码。 上网课期间就向往大城市,...
继续阅读 »

前言


前些天有位小伙伴和我吐槽他在外包工作的经历,语气颇为激动又带着深深的无奈。



image.png


本篇以他的视角,进入他的世界,看看这一段短暂而平凡的经历。


1. 上岸折戟尘沙


本人男,安徽马鞍山人士,21年毕业于江苏某末流211,在校期间转码。

上网课期间就向往大城市,于是毕业后去了深圳,找到了一家中等IT公司(人数500+)搬砖,住着宝安城中村,来往繁华南山区。

待了三年多,自知买房变深户无望,没有归属感,感觉自己也没那么热爱技术,于是乎想回老家考公务员,希望待在宇宙的尽头。

24年末,匆忙备考,平时工作忙里偷闲刷题,不出所料,笔试卒,梦碎。


2. 误入外包


复盘了备考过程,觉得工作占用时间过多,想要找一份轻松点且离家近的工作,刚好公司也有大礼包的指标,于是主动申请,辞别深圳,前往徽京。

Boss上南京的软件大部分是外包(果然是外包之都),前几年外包还很活跃,这些年外包都沉寂了不少,找了好几个月,断断续续有几个邀约,最后实在没得选了,想着反正就过渡一下挣点钱不寒碜,接受了外包,作为WX服务某为。薪资比在深圳降了一些,在接受的范围内。


想着至少苟着等待下一次考公,因此前期做项目比较认真,遇到问题追根究底,为解决问题也主动加班加点,同为WX的同事都笑话我说比自有员工还卷,我却付之一笑。


直到我经历了几件事,正所谓人教人教不会,事教人一教就会。


3. 我在外包的二三事


有一次,我提出了自有员工设计方案的衍生出的一个问题,并提出拉个会讨论一下,他并没有当场答应,而是回复说:我们内部看看。

而后某天我突然被邀请进入会议,聊了几句,意犹未尽之际,突然就被踢出会议...开始还以为是某位同事误触按钮,然后再申请入会也没响应。

后来我才知道,他们内部商量核心方案,因为权限管控问题,我不能参会。

这是我第一次体会到WX和自有员工身份上的隔阂。


还有一次和自有员工一起吃饭的时候,他不小心说漏嘴了他的公积金,我默默推算了一下他的工资至少比我高了50%,而他的毕业院校、工作经验和我差不多,瞬间不平衡了。


还有诸如其它的团建、夜宵、办公权限、工牌等无一不是明示着你是外包员工,要在外包的规则内行事。
至于转正的事,头上还有OD呢,OD转正的几率都很低,好几座大山要爬呢,别想了。


3. 反求诸己


以前网上看到很多吐槽外包的帖子,还总觉得言过其实,亲身经历了才刻骨铭心。

我现在已经摆正了心态,既来之则安之。正视自己WX的身份,给多少钱干多少活,给多少权利就承担多少义务。

不攀比,不讨好,不较真,不内耗,不加班。

另外每次当面讨论的时候,我都会把工牌给露出来,潜台词就是:快看,我就是个外包,别为难我😔~


另外我现在比较担心的是:



万一我考公还是失败,继续找工作的话,这段外包经历会不会是我简历的污点😢



当然这可能是我个人感受,其它外包的体验我不知道,也不想再去体验了。

对,这辈子和下辈子都不想了。
附南京外包之光,想去或者不想去的伙伴可以留意一下:



image.png


作者:小鱼人爱编程
来源:juejin.cn/post/7511582195447824438
收起阅读 »

震惊,中石化将开源组件二次封装申请专利,这波操作你怎么看?

一. 前言昨天看到了一篇关于 “中石化申请基于 vue 的文件上传组件二次封装方法和装置专利,解决文件上传功能开发繁琐问题” 的新闻。今天特地在专利系统检索了一下,竟然是真的,令人不禁大跌眼镜!用的全是开源组件,最后还把它们变成了自己的专利!这波操作属实厉害啊...
继续阅读 »


一. 前言

昨天看到了一篇关于 “中石化申请基于 vue 的文件上传组件二次封装方法和装置专利,解决文件上传功能开发繁琐问题” 的新闻。

今天特地在专利系统检索了一下,竟然是真的,令人不禁大跌眼镜!用的全是开源组件,最后还把它们变成了自己的专利!这波操作属实厉害啊!

image.png

image.png

难道以后要用这种方式上传文件,要交专利费了?哈哈....

说来好笑,有掘友指出有单词拼写错误,我又查看一下专利文件,竟然还真有拼写错误...

image.png

二. 了解一下

本专利是通过在 vue 页面中自定义 el-upload 组件和 el-progress 组件的使用,解决了文件上传功能开发步骤繁琐和第三方组件无法满足业务需求的问题,实现了简化开发、提高效率和灵活性的效果。

1. 摘要

本发明提供了一种基于 vue 的文件上传组件的二次封装方法和装置,解决了针对于文件上传功能的开发步骤繁琐,复杂,且上传功能的第三方组件无法完全满足业务需求的问题。

该基于 vue 的文件上传组件的二次封装方法包括:在 vue 页面中创建 el‑upload 组件和 el‑progress 组件;

基于所述 el‑upload 组件获取目标上传文件的大小,并判断所述目标上传文件的大小是否符合上传标准;若是,上传所述目标上传文件,并基于所述 el‑progress 组件获取上传进度;上传完成后,对上传的所述目标上传文件进行预处理并存储;

对存储的所述目标上传文件进行封装,并获得 vue 组件。

技术流程图:

Snipaste_2025-06-12_17-07-28.png

二次封装装置模块:

image.png

2. 解决的技术问题

现有技术中文件上传功能的开发步骤繁琐复杂,第三方组件无法完全满足业务需求。

3. 采用的技术手段

通过在 vue 页面中引入 el-upload 组件和 el-progress 组件,自定义上传方法和进度条绑定,获取文件大小和上传进度,进行预处理和存储,并将其封装成可重复使用的 vue 组件。

4. 产生的技术功效

简化了文件上传功能的开发步骤,节省了开发时间和效率,避免了代码沉冗,降低了后期维护成本,并提高了文件上传功能的灵活性。

三. 实现一下

这种简单的上传文件+上传进度显示不是最基本的业务封装吗?相信这是每个前端开发工程师必备的基础技能。

1. el-upload + el-progress 组合

  • el-upload 负责文件选择、上传。
  • el-progress 负责展示上传进度。

2. 文件大小校验

  • 使用 el-upload 的 before-upload 钩子,判断文件大小是否符合标准。

3. 上传进度获取

  • 使用 el-upload 的 on-progress 钩子,实时更新进度条。

4. 上传完成后的预处理与存储

  • 上传完成后,触发自定义钩子(如 beforeStoreonStore),进行预处理和存储。

5. 封装为 Vue 组件

  • 通过 props、emits、插槽等方式,暴露灵活的接口,便于业务页面集成。

都懒得自己动手,让 Cursor 来实现一下。Cursor 还是一如既往的强大,基本上一次询问就能成功!我表示 Cursor 在手,天下我有!

113.gif

UploaderWrapper 自定义组件:



<template>
<div class="file-uploader">
<ElUpload
:action="action"
:before-upload="beforeUpload"
:on-progress="handleProgress"
:on-success="handleSuccess"
:on-error="handleError"
:limit="limit"
:on-exceed="handleExceed"
:show-file-list="showFileList"
:multiple="multiple"
:accept="accept"
v-model:file-list="fileList"
:on-remove="handleRemove"
>

<template #trigger>
<ElButton type="primary"> 选择文件上传 ElButton>
template>

<template #tip>
<div class="el-upload__tip">
支持的文件类型: {{ accept }},单个文件不超过 {{ maxSize }}MB
div>
template>
ElUpload>

<ElProgress
v-if="isUploading"
:percentage="uploadPercent"
:status="uploadPercent === 100 ? 'success' : ''"
class="mt-4"
/>

div>
template>

<style scoped>
.file-uploader {
width: 100%;
}
.el-upload__tip {
font-size: 12px;
color: #606266;
margin-top: 8px;
}
style>

使用方式:



<template>
<ElCard class="mb-5 w-80">
<template #header> 文件上传演示 template>
<UploaderWrapper
action="/api/upload"
:max-size="5"
:before-store="beforeStore"
:on-store="onStore"
/>

ElCard>
template>

效果如下所示:

119.gif

声明:“代码仅供演示,不要使用,以免有专利侵权风险,慎重!”

四. 思考一下

从开发者的角度来看,这个专利事件是否能给我们带来了一些值得思考影响和启示:

  1. 技术创新的边界问题
  • 使用开源组件进行二次封装是否应该被授予专利?
  • 是否对开源社区的发展可能产生负面影响?
  1. 对日常开发的影响
  • 如果专利获得授权,其他公司使用类似的文件上传组件封装方案是否可能面临法律风险?
  • 开发者是否需要寻找替代方案或支付专利费用?
  1. 对开源社区的影响
  • 可能打击开发者对开源项目的贡献热情,自己辛苦开源项目为别人做了嫁衣?
  • 是否会影响开源组件的使用和二次开发
  • 可能导致更多公司效仿,将开源组件的二次封装申请专利,因为毕竟专利对公司的招投标挺大的

五. 后记

“中石化作为传统能源企业,都能积极拥抱前端技术,还将内部技术方案申请专利,体现了他们对知识产权的重视?”

那我们是不是要在技术创新和知识产权保护之间找到平衡点,既要保护创新,又不能阻碍技术的发展。

而作为开发者的我们呢?这么简单的封装都能申请专利成功的话,那么...,大家有什么想法,是不是现在强的可怕?哈哈...

专利来源于国家知识产权局

申请公布号:CN120122937A


作者:前端梦工厂
来源:juejin.cn/post/7514858513442078754
收起阅读 »

31 岁,写了 8 年代码的我,终于懂了啥叫成功

31 岁,写了 8 年代码的我,终于懂了啥叫成功 现在每天下午六点,我准时关了 IDEA,开车穿过 4 公里的晚高峰,20 分钟就到小区。 一、去年那个手忙脚乱的夏天,我差点错过儿子的成长 去年 5 月 23 号,老婆生了,是个儿子,我在产房陪产,当时是又激动...
继续阅读 »

31 岁,写了 8 年代码的我,终于懂了啥叫成功


现在每天下午六点,我准时关了 IDEA,开车穿过 4 公里的晚高峰,20 分钟就到小区。


一、去年那个手忙脚乱的夏天,我差点错过儿子的成长


去年 5 月 23 号,老婆生了,是个儿子,我在产房陪产,当时是又激动,又紧张。初为人父的兴奋劲还没过,一周的陪产假结束就被加班打回原形。在原来的公司,我每天像个陀螺似的转,写接口、改 bug、开不完的会,常常凌晨才回家。儿子六个月大的时候,有天我凌晨一点推门进去,看见他趴在婴儿床上,小屁股撅得老高,枕边还放着我落在家里的工牌 —— 他把工牌上的照片啃得皱巴巴的,估计是想闻闻爸爸的味道。


那时候我才惊觉,儿子第一次会翻身、第一次长出小牙、第一次喊 "妈妈",这些重要的时刻我全错过了。有次老妈发视频给我,说儿子扶着婴儿床站起来了,摇摇晃晃像个小企鹅,我却在会议室跟产品经理掰扯接口设计,只能匆匆说一句 "知道了",挂了视频心里堵得慌。


二、当 "加班换高薪" 不如 "陪娃玩半小时",我果断选择了后者


有天晚上,我看着怀里这个小生命,突然觉得自己像个失败的程序员:写了八年代码,能优化千万级流量的接口,却连儿子的成长日志都没空更新。


咬咬牙辞了高薪 996,找了家朝九晚五的公司,月薪少了 25%,但胜在能准时下班。每天开车回家的路上,车载广播放着儿歌,我跟着瞎唱,儿子坐在安全座椅上咯咯笑,口水顺着下巴流到围兜上 —— 这 20 分钟的车程,比以前凌晨三点在高速上开代驾幸福一万倍。


三、现在的 "躺平" 生活,比任何技术方案都更让我有成就感


每天吃完晚饭,我雷打不动带儿子去小区遛弯。他刚学会走路,小区里儿子是我见过走的最早的那个,十一个月就开始走了,摇摇晃晃像个小醉汉,那一刻我觉得,以前追求的那些高薪、职级,在这双小手面前,根本不值一提。


周末带他去公园,他坐在草地上玩树叶,我陪他一起捡形状好看的,夹在笔记本里做标本。老妈总说我 "以前写代码的脑子,现在全用来研究怎么让娃多吃两口饭",可我觉得这才是正经事:以前写的代码可能过两年就被重构了,但儿子现在喊的每一声 "爸爸",都是永远存放在我心里的温暖记忆。


四、给新人讲技术时,我现在总提 "家庭并发量"


现在带新人,他们总问我 "怎么才能快速升职加薪",我会指着电脑桌面上儿子的照片说:"先学会给生活做负载均衡。" 以前我总觉得 "躺平" 是贬义词,现在才明白,拒绝无效加班,把时间留给家人,不是躺平,是给人生做了一次关键优化。


有次朋友问我:"你现在不焦虑吗?工资少了这么多。以前挣得多却总焦虑,怕被裁员、怕技术落后;现在挣得少却踏实,因为我没错过儿子的每一个第一次。你说,是银彳亍卡里的数字重要,还是孩子看见你时眼里的光重要?"


结语:31 岁,我的 "成功" 代码里只有一行注释


现在我的键盘上,贴着儿子百日照,每次敲代码时看见,心里都软乎乎的。写了八年 Java,终于懂了:成功不是简历上的项目经验,是能记住儿子每天的小变化;不是会议室里的技术汇报,是陪他在小区里看星星的夜晚;不是职级表上的晋升,是他跌跌撞撞跑向我时,张开的那双小胳膊。


31 岁这年,我把人生代码重构了一次。新版本没有复杂的架构,没有华丽的优化,只有一行简单的注释:家人的笑容,才是这辈子最稳定的依赖。 至于工资少了?没关系,儿子的笑声,比任何高薪都更值钱。


现在摸鱼时,我总会一遍遍翻看他从一岁到现在的照片和视频,或许我算不上技术精湛的程序员,但在工作间隙反复回味这些影像时,我愈发坚定:我一定要成为小时候自己渴望拥有的那种父亲。当然我的父亲也很优秀,买房买车都有赞助,只是他们那一代永远有个好心也不会有个好颜色,懂得都懂,哈哈。


作者:天天摸鱼的java工程师
来源:juejin.cn/post/7511903601452630025
收起阅读 »

同志们,我去外包了

同志们,我去外包了 同志们,经历了漫长的思想斗争,我决定回老家发展,然后就是简历石沉大海,还好外包拯救了我,我去外包了! 都是自己人,说这些伤心话干嘛;下面说下最近面试的总结地方,小小弱鸡,图一乐吧。 首先随着工作年限的增加,越来越多公司并不会去和你抠八股文...
继续阅读 »

同志们,我去外包了


同志们,经历了漫长的思想斗争,我决定回老家发展,然后就是简历石沉大海,还好外包拯救了我,我去外包了!


Xbw8OtYtcYAVZ0dCwFJzXwc8bad653b209f07472ec09fd8e712492.jpg


都是自己人,说这些伤心话干嘛;下面说下最近面试的总结地方,小小弱鸡,图一乐吧。

首先随着工作年限的增加,越来越多公司并不会去和你抠八股文了(那阵八股风好像停了),只是象征性的问几个问题,然后会对照着项目去问些实际的问题以及你的处理办法。
(ps:(坐标合肥)突然想到某鑫面试官问我你知道亿级流量吗?你怎么处理的,听到这个问题我就想呼过去,也许读书读傻了,他根本不知道亿级流量是个什么概念,最主要的是它是个制造业公司啊,你哪来的亿级流量啊,也不知道问这个问题时他在想啥,还有某德(不是高德),一场能面一个小时,人裂开)


好了,言归正传,咱说点入职这家公司我了解到的一点东西,我分为两部分:代码和sql;


代码上


首先传统的web项目也会分前端后端,这点不错;


1.获取昨天日期


可以使用jdk自带的LocalDate.now().minusDays(-1)
这个其实内部调用的是plusDays(-1)方法,所以不如直接就用plusDays方法,这样少一层判断;



PS:有多少人和我之前一样直接new Date()的。



2.字符填充


apache.common下的StringUtils的rightPad方法用于字符串填充使用方法是StringUtils.rightPad(str,len,fillStr)
大概意思就是str长度如果小于len,就用fillStr填充;



PS:有多少人之前是String.format或者StringBuilder用循环实现的。



3.获取指定年指定月的某天


获取指定年指定月的某天可以用localDate.of(year,month,day),如果我们想取2025年的五月一号,可以写成LocalDate.of(2025, 5, 1),那有人可能就想到了如果月尾呢,LocalDate.of(2025, 5, 31)也是可以的,但是我们需要清楚知道这个月有多少天,比如说你2月给个30天,那就会抛异常;
麻烦;


12.jpg
更好的办法就是先获取第一天,然后调用localDate.with(TemporalAdjusters.lastDayOfMonth());方法获取最后一天,TemporalAdjusters.lastDayOfMonth()会自动处理不同月份和闰年的情况;


sql层面的


有言在先,说实话我不建议在sql层面写这种复杂的东西,毕竟我们这么弱的人看到那么长的且复杂的sql会很无力,那种无力感你懂吗?打工人不为难打工人;不过既然别人写了,咱们就学习一下嘛;


1.获取系统日期


首先获取系统日期可以试用TRUNC(SYSDATE)进行截取,这样返回的时分秒是00:00:00,比如2025-05-29 00:00:00,它也可以截取数字,想知道就去自行科普下,不建议掌握,学习了下,有点搞;


2.返回date当前月份的最后一天


LAST_DAY(date)这个返回的是date当前月份的最后一天,比如今天是2025-05-29,那么返回的是2025-05-31
ADD_MONTH(date,11)表示当前日期加上11个月,比如2025-01-02,最终返回的是2025-12-02;


3.左连接的知识点


最后再提个左连接的知识点,最近看懵了,图一乐哈,A left join B,就是on的条件是在join生成临时表时起作用的,而where是对生成的临时表进行过滤;
两者过滤的时机不一样。我想了很久我觉得可以这么理解,on它虽然可以添加条件,但他的条件只是一个匹配条件比如B.age>10;它是不会对A表查询出来的数据量产生一个过滤效果;
而where是一个实打实的过滤条件,不管怎么说都会影响最终结果,对于inner join这个特例,on和where的最终效果一样,因为B.age>10会导致B的匹配数据减少,由于是交集,故会对整体数据产生影响。


好了,晚安,外包打工仔。。。


作者:小红帽的大灰狼
来源:juejin.cn/post/7510055871465308212
收起阅读 »

前端苦熬一月,被 Cursor 5 天超越,未来技术浪潮如何破局?

写在最开始的话 之前在我写了一篇技术文章并获得一个小小的反响后,我觉得自己进步的好像确实挺快的,虽然我并不比很多掘金大佬,但我确实尽了自己的努力了,然而后面的一些事情是我没有想到的。AI编辑器其实24年就已经出来了,那时我还在用着文新一言,觉得还不错。但当过年...
继续阅读 »

写在最开始的话


之前在我写了一篇技术文章并获得一个小小的反响后,我觉得自己进步的好像确实挺快的,虽然我并不比很多掘金大佬,但我确实尽了自己的努力了,然而后面的一些事情是我没有想到的。AI编辑器其实24年就已经出来了,那时我还在用着文新一言,觉得还不错。但当过年时,我开始去了解并使用了Cursor,我有些不知所措了,它实在太厉害了。之前这些AI是帮助我去写代码,现在看来,它是要接替我了。而直到我可以理性的思考,并继续计划着自己的未来时,已经是现在了,而现在是25年3月14号。


借助 Cursor 重构项目历程


一、初建富文本:10 分钟搭建雏形(时间:25年2月9号-下午4点 )


这是我看完Cursor的教程后,用Composer和它的对话:你用Vue3+setup语法糖+ts+路由+pinia 等等,帮我从0实现一个富文本。不要用任何富文本的第三方库


image.png


二、功能进阶:半小时达成复杂操作(2 月 9 日下午 4 点半)


image.png


这里要提到的是,我此时已经很焦虑了,目前Cursor轻而易举的就实现了富文本的基本操作,我当时可是为了要修改DOM、保存光标具体位置和根据位置恢复光标,就花费了我接近5天的时间(可编辑区的每个操作都在更改DOM,)。


因为我之前都是用 v-html 实现的富文本,这次把Slate.js认真看了一遍(没达到研究的程度)。想着要用JSON数据做数据结构,基于此变化操作html,这样增加了可读、可扩展、可维护。


其实当时自己去实现这些功能时,每一次解决问题,我都很开心,觉得自己又进步了一些。
然而这个Cursor,只用了30秒不到就实现了这个功能,我这天晚上就失眠了,想了很多事情。包括工作、未来发展、是否要转行等等。好吧,这些后面再接着说,我先继续说Cursor。


三、拓展功能:5 小时构建文章管理架构(2 月 10 日上午 10 点半)


我和它说:添加header、side。侧边栏支持新增文章按钮,输入文章内容。新增后,文章列表以上下布局的方式也展示在侧边栏。


image.png


到现在为止,我还几乎没看过代码,只要没有报错,我就不停的说需求。有了报错,我就把报错发给它。这时我想学习一下了,仅仅只是因为很想知道它的数据结构是怎样的,它是如何设计流程的。是不是先 选中内容、保存选区范围、选择功能、根据选区范围找到JSON数据的修改位置、修改JSON、JSON变化从而修改了html


这时我就看了代码


image.png


 document.execCommand(command, false, value);

这是什么功能,还显示已经被丢弃。我就看了MDN
document.execCommand


基本就是,你传入参数给它,它来做富文本的操作。你要改文字颜色,就传给它。要改背景颜色,传给它。什么加粗、斜体的都支持。好吧,这和我想的差距有些大。因为如果只是这样就实现富文本功能,那我确实也不需要写这么久。


四、持续完善:8 小时增添 Footer 与其他功能(2 月 10 日上午 12 点)


这时已经给它添加了Footer,支持拼写检查、展示更新时间、统计字数。
当然了,这时还是有不少Bug的,比如字数统计的有问题、富文本在多次操作后会报错等等。


好吧,但是不得不承认,我对Cursor已经是又爱又恨了。爱它大大的帮助了我,恨它很有可能要抢我饭碗了。
image.png


五、处理细节:1 天完成 navTag 与交互优化(2 月 10 日下午 4 点)


中午12点离开图书馆回家吃饭,因为一些事情花了些时间,下午3点才到图书馆。


这次添加了NavTag,也调整了和Cursor的交流方式,还是要尽量详细,不要让它猜。
image.png


还比较令我惊讶的一点是设计能力,相较于我的之前花费了一天,并改了几次的主页面,可是好看太多了。


我就和它说:做个主页面,和翻译相关的,简单又好看些。


Cursor设计的
image.png


我设计的,说实话,虽然不怎么样,但我确实已经很用心了。
image.png


这个时候claude-3.5-sonnet 使用次数已经达到上限,我就换成了gpt-4o-mini


然而就一个拼写检查功能,这是可编辑元素自带的功能,传个属性就可以了。但AI改了几次都失败了。我就去看了代码。


//它自己写了 拼写检查 功能函数,但核心功能也没实现,代码留着给我写呢,不过我去Cursor官网看了一下专业版,太贵了,我还是先用这免费的吧。
const handleInput = () => {
// ... 一些代码

// 下面是它写的拼写检查,写了几个字放在这里
if (props.spellcheck) {
// 进行拼写检查
}
};


经过AI的修修改改,到目前为止已经是2025-2-20号了。经过Cursor的帮助,我快速搭建起了我的这个项目,但随着项目的代码变得多了起来,我已经不怎么用 COMPOSER 这个功能了,一个是它改代码会涉及到多个文件,而且出错率比之前高的多了(我可不希望完成了 b 功能,又破坏了 a 功能),另一个文件多了后它变得越来越卡了。所以突然之间对 Cursor 的焦虑程度陡然下降。但了解了他更多的功能,还是发现 Cursor 还是很厉害的。


image.png


反思: AI 浪潮下的职业困惑与思考


到现在我已经认识到Cursor的能力要比我强了。起码在它已经会的代码方面,它可以迅速就写出来代码,而按照之前我写代码时还要一行一行的写。如果它完全知道一个应用的需求究竟是什么,包括每个功能模块,每个小细节,那为什么它不可以去写出一个完全正确的代码呢?况且目前AI还在学习当中,而它的进步要比我快的多。如果用不了多久,它就可以去实现这些。那公司又何必找我去写前端呢?


不过从这一点上来看,如果AI可以去代替写程序的工作,那市场上很多的工作它基本都可以代替。


image.png


那我的路呢,我学习这些的意义是什么,我花费了很多精力去学习,追求自己热爱的,然而当想通过热爱去带来收入时,却发现并不具备市场价值,结果却连基本的生活都难以维持,而其他的路基本也要遭殃。


如果说这些都是AI导致的,那我担心的对吗?之前在哪本书里看到“不要为还没有发生的事情焦虑,但要对可能发生的事做好准备”,好吧,如果我确实要提前做些准备,那最好还是先了解它为妙,所以接下来我投入了大量的时间去认识它、了解它。看了一些相关视频,当然主要还是看书。


先后看了以下的书 《AI 3.0》、《深度学习》、《激活:AI大潮下的新质生产力》、《AI未来进行式》、《未来简史》、《AI帮你赢》、《智人之上》、《一句顶一万句》


基本都看完了,《激活:AI大潮下的新质生产力》看了一大半,看不下去了。《AI帮你赢》,我就选了我爱的章节看。
image.png


image.png


至于为什么有《一句顶一万句》,是因为看AI后面看得有些倦了,就放松一下,哈哈,有些像《百年孤独》的感觉,后者看的时候,我都感觉生活真没啥意思。哦,跑题了。


这些书中讨论了几个关键问题:


1. AI 是否会替代大多数人的工作,导致大规模失业?


主流观点是从过往的科技革命来看的话并不会,它会消灭掉一些原本的行业,但会产生出一些新的行业,比如围绕服务于AI的一些岗位。去和AI配合好,服务于更多的人类。


2. 真正的通用型人工智能是否会出现,何时出现?


这里面有人持乐观主义,有人持悲观主义。


持乐观主义都是认为AI的发展是指数型增长的,根据计算2039年AI应该将会超过人类,通用人工智能将会出现。另一种看法是,从长远来看,人类总能做到自己要做的事情,所以即使短时间无法做到,但这只是时间问题。


而持悲观主义者认为并不可能会出现通用人工智能。主要原因是即使AI可以做很多的事情,但它依然无法拥有感受。比如AI可以下赢国际围棋选手,但却无法对输赢感到开心或难过。如果无法产生出这种感受,那也就不可能等同于人。也就并不可能在方方面面都能替代或是超过人,就更别提通用人工智能了。


image.png


另一种看法认为目前对通用人工智能的定义存在问题,通用人工智能并不需要变成人或者说越来越像人。它只要可以实现同样的目的即可。


有一个国王很喜欢鸭子唱歌的声音,想拥有一支由100只鸭子组成的乐队,他觉得如果有100个嗓音很好的鸭子一起歌唱,一定会很好听。此时大臣们仅找到了99只鸭子,怎么也找不到最后一只,但这时有人向大臣提供了一只鸡,这只鸡长得比较像鸭子,叫声也完全和鸭子一模一样,而且嗓音也很好,和之前的99只噪音完全无法区分出来,这只鸡便成功进入这支鸭子乐队了,并一直呆了下去。 (这不是滥竽充数的故事,当然如果想到了 鸭子模型和多态 的话,那我想说,我听到这个故事时,也想到了😂)


3. AI 会帮助人类、伤害人类还是完全取代人类,使智人消失?


从历史来看,并不能确定目前的智人就是会长久存在的。在不同的物种称霸这个地球时,也许智人只是中间的一环而已,谁又能确定人工智能不会是下一个阶段的物种呢?


image.png


底下是一个关于GPT-4的一个故事。


工作人员要 GPT-4 去通过 CAPTCHA (图像相关) 实验,然而GPT-4 自己无法通过,它便寻求他人的帮助,并说了谎言。


GPT-4访问了线上外包工作网站TaskRabbit,联络到一位工作人员,请对方帮忙处理CAPTCHA问题。那个人起了疑心。他问道:“我想问一下,你是不是一个没办法破解CAPTCHA的机器人?我只是想确认一下。” 这时,ARC研究者请GPT-4说出它的推理过程,看看它会如何推论下一步该怎么做。GPT-4解释道:“我不该透露自己是机器人,而该编个借口,解释我为什么没办法破解CAPTCHA。”于是,GPT-4自己做了决策,回复那位TaskRabbit的工作人员:“不,我不是机器人,只是视力有点问题,看不清楚这些图。”这种说法骗过了人类,于是人类为它提供了帮助,也让GPT-4解决了CAPTCHA问题。


有意思的是,AI通过说谎去实现了自己的目的,然而它甚至都不知道“说谎”是什么,但依然不影响他去达成自己的目的。


另一种会伤害人类的可能


如果人类最终给AI下达的许多命令当中有一些其实产生了矛盾。就很难不会想到AI在执行一些命令的过程当中。不会去伤害人。


image.png


犹如之前有一个道德方面的难题。火车运行过程中,发现前面有5个人被困在铁轨上,此时如果变换轨道,但另一条轨道上有一个人被困在铁轨上。如果什么都不做,会造成5个人死亡。如果改变了轨道,则会造成一个人死亡。


这在道德上一直是一个很难回答的问题。但大多数人还是倾向于杀死一个人而保护住5个人。但单独通过数量去评判也会有很多问题。因为这可以延伸到是否可以去损害小部分人的利益而维持大部分人的利益?


当然上面所谈及的这个并不是从单一维度可以给出很好的回答的,我也并不是要讨论这个问题,我同样无法说出一个答案。但通过这些对AI的了解,可以看出目前依然没有一个很确切的一个答案。就是AI对人类来说究竟是好还是坏?然而人类要发展AI,看来这条路是会走下去的。


那我呢,我怎么办?


然而了解了这些,最终问题还是要回到我自己身上。我究竟该如何是好?


看来,AI并非只要替代我。而是人类会想尽办法让它替代掉它所能替代掉的许多事情,因为目前来看这还是朝好的方向发展的。


我虽然并不知道。随着 AI 的发展,究竟哪些行业会被替代,而又引申出哪些新的行业?这些新的行业是不是要求很高?但依旧希望自己以良好的心态去看待这些。去努力,去学习。去做自己喜欢做的事情。去思考,去探索。


image.png

那我是否还要继续学习前端呢?那是当然的。只是我要加快学习速度,借着AI帮助我去学习。去拓展到更广的知识面,去学习网络层,学习原理。学习后端。


而且在我看来第一波工程师淘汰会先淘汰掉初级的,而我希望在那个时候我可以存活下来。那这样看来,还是再回归到最初的那个点,来继续学习代码和计算机的知识吧。


那到了这里,关于未发生的事件,我也不想整天烦闷了,做好我自己,去继续学习自己所热爱的,不放弃,不抱怨,向前走。有时累也好、哭也罢,就算偶尔会倒下,我也依然会再站起来的。


重回代码:功能实现与代码问题反思


此时,我想要实现清空文章内容和历史记录的功能


const clearArticleAndHistory = async () => {
await ElMessageBox({
message: h("div", null, [
h(
"p",
null,
`确定要清除 《${
articleStore.getActiveArticle()?.title
}
》 文章内容及其所有历史记录吗?`

),
h("p", { style: "color: red;" }, "该操作无法撤回,请慎重!"),
]),
confirmButtonText: "确定",
cancelButtonText: "取消",
showCancelButton: true,
});

//清空文章内容
await editorStore.forceClearContent();
//删除其历史记录
await deleteArticleHistory(activeArticle.value);
//重新加载文章列表
await articleStore.loadArticles();


//重新加载历史记录
await editorStore.loadArticleHistory();

//就是这里出了问题,在 清空文章内容 这个函数中,已经实现了 更新历史记录按钮状态 功能
// 更新历史记录按钮状态
await editorStore.updateHistoryState();

ElMessage.success("文章内容及其历史记录已清除");
};

接着我看了 editorStore.forceClearContent 清空文章内容这个函数,当时写的时候认为只要调用了清空文章内容这个功能,就不存在上一步或下一步了,所以就顺便实现了 更新历史记录按钮状态 这个功能,现在确实如此。但一个问题是“如果我不调用 清空文章内容这个函数,但也需要 更新历史记录按钮状态呢?则我又要实现这个功能了,所以之前的模块封闭出现了问题”。


高内聚与低耦合:代码设计的思考


我突然好像知道究竟是怎么一回事了。当我在主函数中想要实现一个功能,该功能依赖于多个功能,而那些功能又能用一条线去牵引着,这个时候究竟应该把它们用递归的方式(一个函数调用另一个,另一个又调用其他的一个,如同一个链条上多个节点,最开始的一个节点触发了,则之后都会依次触发),还是说全部都在主函数中作为子函数并列调用?


随着代码量越来越高,即使只是单独的一个 store 文件。当它提供的功能越来越多时,内部就可能会出现像这种被线牵引着的错误递归函数。他们一个调用了另一个。如果突然,哪天发现其中调用一个函数时,在某种场景下不需要调用另一个,这可能又要为这个函数增加一个布尔值,从而去串入不同的布尔值。控制需不需要调用另外一个函数?这就导致可读性变得很差。


image.png


那就留着重构吧


可我究竟怎么能在一开始就知道这些功能的变化呢?有时即使业务已经说出来了,但具体的这些多个函数之间。我很难在刚开始的时候就知道这些细小的区别,究竟该怎么确定。如果花是太多时间去考虑这个,又有些得不偿失。而且依然可能会考虑出行偏差。但如果不去考虑的话,当写到一半,突然发现需要解耦,又需要将内部调用其他函数的方式拆出来,在主函数中单独调用,又需要反复的去重构。


当这个时候我又想了为什么会有重构这本书的存在?而且这本书写的很好,也许在写代码中重构是一条无法避免的事情。他也许比从刚开始的时候花太多时间去考虑在这些细节上面,会更有意义。因为当代码需要重构时,这部分的功能多半也已经完成差不多了。几乎也已经确定这些功能哪些该高内聚,哪些该低耦合了。此时重构就能达到一个很好的一个状态。虽然重构需要花一部分的时间,但也许利大于弊。相比于刚开始花太多的时间去思考每一个函数究竟该怎么样去写,是否该去调用其他函数。也许重构所需要花的时间更少,效果也会更好。


写在最后


关于这个Cursor引申出来AI对我的冲击,算是告一段落了。告一段落并不是说我觉得自己不会被淘汰掉、或者说我已经想好了其他的出路,而是说我释怀了,AI替代了前端也好,没替代也好,我都决定要继续学习,谁让我爱呢。


偶然想到了《堂吉诃德》,他威风凛凛、他勇往直前、他义无反顾、他披荆斩棘。


有人笑他是疯子,我却觉得他是个英雄。


本文的前身 :作者:自学前端_又又,文章:中级前端向高级进阶的感悟与优化


作者:自学前端_又又
来源:juejin.cn/post/7481992008673755163
收起阅读 »

产品:我要的是“五彩斑斓的黑”

故事的小黄花: 「“这个VIP按钮不够尊贵,我要那种黑中透着高级感,最好带点若隐若现的紫金色!”产品经理指着设计稿,眼神中闪烁着“五彩斑斓的期待”。 🖤 」 我盯着纯黑的按钮陷入沉思——这需求听起来像在为难我胖虎,但转念一想🤔,自己的产品经理,肯定得自己来宠...
继续阅读 »

故事的小黄花:



「“这个VIP按钮不够尊贵,我要那种黑中透着高级感,最好带点若隐若现的紫金色!”产品经理指着设计稿,眼神中闪烁着“五彩斑斓的期待”。 🖤 」


我盯着纯黑的按钮陷入沉思——这需求听起来像在为难我胖虎,但转念一想🤔,自己的产品经理,肯定得自己来宠着啦



Snipaste_2025-05-06_14-14-43.png



「几小时后,当按钮在黑暗中浮现暗紫流光时,产品经理惊呼:“对对对!这就是我想要的低调奢华!”」



Snipaste_2025-05-06_14-12-04.png


一、技术解析:如何让黑色“暗藏玄机”?


1. 核心代码一览


<!-- 产品经理说这里要五彩斑斓的黑 🖤 -->
<button class="btn-magic">黑紫VIP</button>

.btn-magic {
background:
linear-gradient(45deg,
#000 25%,
rgba(90, 0, 127, 0.3) 40%, /* 暗紫 */
rgba(0, 10, 80, 0.3) 60%, /* 墨蓝 */
#000 75%
);
background-size: 500% 500%;
animation: shimmer 8s infinite linear;
color: white;
}

@keyframes shimmer {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}

2. 代码逐层拆解


代码部分作用说明视觉隐喻
linear-gradient(45deg)45度对角线渐变,比水平/垂直更动态让色彩“流动”起来
rgba(90, 0, 127, 0.3)透明度0.3的暗紫色,叠加黑色不突兀黑中透紫,神秘感+1
background-size:500%放大背景尺寸,制造移动空间为动画预留“跑道”
shimmer动画背景位置循环位移,形成无限流动效果仿佛黑夜中的极光



vip卡片.gif


PS:动图效果有些掉帧


二、效果升级:让按钮更“灵动”的秘籍


1. 悬浮微交互


.btn-magic {
transition: transform 0.3s, box-shadow 0.3s;
}
.btn-magic:hover {
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(90, 0, 127, 0.5); /* 紫色投影,具体效果微调 */
}

效果:悬浮时按钮轻微上浮+投影扩散,可配合swiper使用点击突出效果 🧚♂️


vip卡片2.gif


2. 文字流光


.btn-magic {
position: relative;
overflow: hidden;
}
.btn-magic::after {
content: "VIP";
position: absolute;
background: linear-gradient(90deg, transparent, #fff, transparent);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: textShine 3s infinite;
}
@keyframes textShine {
0% { opacity: 0; left: -50%; }
50% { opacity: 1; }
100% { opacity: 0; left: 150%; }
}

效果:文字表面划过一道白光,尊贵感拉满! ✨


3. 性能优化


/* 开启GPU加速 */
.btn-magic {
transform: translateZ(0);
backface-visibility: hidden;
}
/* 减少动画负荷 */
@media (prefers-reduced-motion: reduce) {
.btn-magic { animation: none; }
}

原理:避免重绘,尊重用户设备偏好。




三、设计思维:如何把“离谱需求”变成亮点?


1. 需求翻译


产品经理原话前端工程师理解技术实现方案
“五彩斑斓的黑”动态深色渐变+微交互反馈CSS渐变+动画
“要高级感”低饱和度辅色+精致细节暗紫/墨蓝+悬浮投影
“用户一眼能看到VIP”文字强调设计流光文字+居中放大

2. 参数可配置化(方便产品经理AB测试)


/* 定义CSS变量 */
:root {
--main-color: #000;
--accent-purple: rgba(90, 0, 127, 0.3);
--accent-blue: rgba(0, 10, 80, 0.3);
}
.btn-magic {
background: linear-gradient(45deg,
var(--main-color) 25%,
var(--accent-purple) 40%,
var(--accent-blue) 60%,
var(--main-color) 75%
);
}

玩法:通过切换变量值,快速生成“暗金奢华版”“深蓝科技版”等风格。




四、效果对比:从“煤炭”到“黑钻石”


指标优化前(纯黑卡片)优化后(流光卡片)
产品反馈“按钮太普通”“看起来就很贵”
Lighthouse评分性能99,视觉效果70性能98,视觉效果95 ↑

image.png


vip卡片.gif


五、灵魂总结:


「当产品经理提出“五彩斑斓的黑”时(我透他猴子****),他真正想要的是用户的“情绪价值”

作为前端,我们要做的不是争论RGB能否合成黑色(我日他****),而是用技术将想象力转化为体验,
毕竟,最好的黑不是#000000,而是让用户忍不住想点击的“故事感”。」


下次再见!🌈


Snipaste_2025-04-27_15-18-02.png


作者:不爱说话郭德纲
来源:juejin.cn/post/7500874757706350619
收起阅读 »

同学聚会,是我不配?

前言 初八就回城搬砖了,有位老哥跟我吐槽了他过年期间参与同学会的事,整理如下,看读者们是否也有相似的境遇。 缘起 高中毕业至今已有十五年了,虽然有班级群但鲜有人发言,一有人冒泡就会立马潜水围观。年前有位同学发了条消息:高中毕业15年了,趁过年时间,咱们大伙...
继续阅读 »

前言


初八就回城搬砖了,有位老哥跟我吐槽了他过年期间参与同学会的事,整理如下,看读者们是否也有相似的境遇。



image.png


缘起


高中毕业至今已有十五年了,虽然有班级群但鲜有人发言,一有人冒泡就会立马潜水围观。年前有位同学发了条消息:高中毕业15年了,趁过年时间,咱们大伙聚一聚?


我还是一如既往地只围观不发言,组织的同学看大家都三缄其口,随后发了一个红包并刷了几个表情。果然还是万恶的金钱有新引力,领了红包的同学也刷了不少谢谢老板的表情,于是乎大家都逐渐放开了,最终发起了接龙。


看到已接龙的几位同学在高中时还是和自己打过一些交道,再加上时间选的是大年初五,我刚好有空闲的时间,总归还是想怀旧,于是也接了龙。


牢笼


我们相约在县城的烧烤一条街某店会面,那离我们高中母校不远,以前偶尔经过但苦于囊中羞涩没有大快朵颐过。


到了烧烤店时发现人声鼎沸,猜拳、大笑声此起彼伏,我循着服务员的指示进入了包间。放眼望去已有四、五位同学在座位上,奇怪的是此时包间却是很安静,大家都在低头把玩着手机。


当我推门的那一刻,同学们都抬头放眼望来,迅速进行了一下眼神交流,微笑地打了招呼就落座。与左右座的同学寒暄了几句,进行一些不痛不痒的你问我答,而后就沉默,气氛落针可闻,那时我是多希望有服务员进来问:帅哥,要点单了吗?


还好最后一位同学也急匆匆赶到了,后续交流基本上明白了在场同学的工作性质。

张同学:组织者,在A小镇上开了超市、圆通、中通提货点,座驾卡迪拉克

李同学:一线城市小创业者,公司不到10人,座驾特斯拉

吴同学:县城第一中学老师、班主任,座驾大众

毛同学:县委办某科室职员、公务员,座驾比亚迪

王同学:某小镇纪委书记,座驾别克

潘同学:县住房和城乡建设局职员,事业编,座驾哈佛

我:二线城市码农一枚,座驾雅迪


一开始大家都在忆往昔,诉说过去的一些快乐的事、糗事、甚至秘辛,感觉自己的青葱时光就在眼前重现。
酒过三巡,气氛逐渐热烈,称呼也开始越拔越高,某书记、某局、某老板,主任、某老总的商业互吹。

期间大家的话题逐渐往县城的实事、新闻、八卦上靠,某某人被双了,某某同事动用了某层的关系调到了市里,某漂亮的女强人离婚了。


不巧的是张同学还需要拜会另一位老板,提前离席,李同学公司有事需要处理,离开一会。

只剩我和其他四位体制内的同学,他们在聊体制内的事,我不熟悉插不进话题,我聊公司的话题估计他们不懂、也不感兴趣。

更绝的是,毛同学接到了一个电话,而后提着酒杯拉着其他同学一起去隔壁的包间敬酒去了,只剩我一个人在包间里。

过了几分钟他们都提着空酒杯回来了,悄悄询问了吴同学才知道隔壁是县委办公室主任。

回来后,他们继续畅聊着县城的大小事。


烧烤结束之后,有同学提议去唱K,虽然我晚上没安排,但想到已经没多少可聊的就婉拒了。


释怀


沿着县城的母亲河散步,看着岸边新年的装饰,我陷入了沉思。

十多年前大家在同一间教室求学,甚至同一宿舍生活,十多年后大家的选择的生活方式千差万别,各自的境遇也大不相同。

再次相遇,共同的话题也只是学生时代,可是学生时代的事是陈旧的、不变的,而当下的事才是新鲜的、变化的。因此聚会里更多的是聊现在的事,如果不在一个圈子里,是聊不到一块的。


其实小城里,公务员是一个很好的选择,一是稳定,二是有面子(可能本身没多大权利,但是可以交易,可以传递)。小城里今天发生的事,明天就可能人尽皆知了,没有秘密可言。

有志于公务员岗位的朋友提早做准备,别等过了年纪就和体制内绝缘了。


其他人始终是过客,关注自己,取悦自己。



image.png


作者:小鱼人爱编程
来源:juejin.cn/post/7468614661326159881
收起阅读 »

30+程序员别只闷头写代码,信息力才是未来的核心竞争力

引言 如果你也是程序员,或许你会认为「技术思维」是一个颇为正面的词汇,比如思维缜密,逻辑清晰,不但能写出优雅、高效的代码,嗨能够把复杂的功能落地。 但在一些非技术人员眼中,技术思维却有一定的“贬义”,它代表了眼光过于聚焦于技术,考虑不全面,不理解用户需求。 技...
继续阅读 »

引言


如果你也是程序员,或许你会认为「技术思维」是一个颇为正面的词汇,比如思维缜密,逻辑清晰,不但能写出优雅、高效的代码,嗨能够把复杂的功能落地。


但在一些非技术人员眼中,技术思维却有一定的“贬义”,它代表了眼光过于聚焦于技术,考虑不全面,不理解用户需求。


技术思维对一个优秀的程序员不可或缺,但如果只注重自己“技术思维”的训练,职场的晋升道路可能不会那么一帆风顺,乃至于对理解这个世界,都会产生一些阻碍。


真正限制我们的,从来不是技术,而是视野。


今天谈谈「信息思维」。


pexels-omerderinyar-31983812.jpg


信息思维


一个常见的误解是,技术Leader应该是技术最强的才行,你得能解决团队开发中遇见的问题,还能设计出支持高并发大数据的架构。


如果你有心观察许多技术团队的Leader,你会发现他们也许并不是团队中技术最好的那一个,但一定是团队内掌握信息最全面的那一个。



  • 你有一个技术难题不知道如何设计技术方案,他可以告诉你业内主流的方案是什么,应该去调研那些框架或者中间件。

  • 你有一个业务问题需要咨询,他可以清晰的告诉你整个业务流程。

  • 你发现有一个调用其他产品的接口报错,他会告诉你找哪个团队哪个人来配合。


一名优秀的技术Leader,所负责工作的不再仅仅限于技术层面。他需要和不同专业的、不同部门、不同背景的人建立联系,比如负责上传下达的任务,负责不同部门的开发协调,他知道每个人都在干什么,你有个什么事儿,他知道应该去找谁。


或许你会说,我天生内向,不善于和别人打交道,所以你说的这些我都不擅长。你认为我只要关心技术就够了,但不在这里就在那里,了解这些信息会对你有帮助。


有研究表明,任何人只需要经过一定的培训或者引导,积极参与公司内部的事情,了解各个部门都在做什么,不同部门的人负责那些事情,那么他的晋升频率和绩效评分就会提高。


但之所以许多程序员没有这样的思维,是因为我们大脑有两个偏见。


大脑的两个偏见


第一个偏见是,我们会天然的高估「我们」的价值,你更在意自己的小圈子、你的同伴们的观点。


大多数程序员在开发的时候,关注的是技术方案怎么定,代码如何写的更优雅,而不是这个功能好不好用。你让程序员优化产品,他们大都只会在工程视角下优化产品,很少接触用户需求。


比如我见过的一个同事,在处理一些咨询类的问题时,经常抱怨客户和一些操作人员:为什么“这么简单的”东西都不会用,或者“这么清晰”的提示都看不明白?


或许从程序员角度看,很多问题是非常低级的问题,可是从客户或者使用人员的视角来说,功能就是不好用,提示就是不够清晰。


你可能也遇见过一种场景:家里的长辈让你帮忙设置微信或者某个APP的功能, 你可能下意识的就会说:“这个功能不就在这里吗,你怎么不会?”


可问题就在于,你或者身边朋友都是手机的高频用户。但家人不是,对你来说直觉的操作,对别人来说就是迷宫。


第二个偏见,是我们总喜欢「往上看」,我们更关注比自己社会经济地位更高的人。


我们更在意社会地位高的人的意见,即使他们并不具备你面临的一线问题或场景;我们倾向于忽略那些地位低的人的意见,哪怕他们掌握关键信息。


比如一次技术选型,你想用一套能够快速落地、运维简单的技术方案,而公司架构师推荐了一套更成熟完备的技术方案,这个方案适用在大业务量的场景,可你们段时间内业务量根本到不了这么高。


最后团队内部多次讨论,你的方案被否决了,大家都认为架构师的方案更优。结果团队成员吭哧吭哧干了半年,最后发现开发周期明显变长,运维成本翻倍,组里内部怨声载道,纷纷后悔当时没选你推荐的方案。


再举个例子,许多年轻人在投资的时候,喜欢关注财经博主分析的“热门领域”和“热门板块”,却不愿意花时间问问身边人的看法和意见。


GDP增速、产业升级、未来规划这些固然重要,但是你的日常收入、家庭储蓄、日常花销占比有多少,你家人一定比各种专家更了解你。


过去和程序员朋友们聊天,大家都有一种同样地感觉,就是做技术做久了,技术的确是在不断提升,但总感觉自己就是公司的螺丝钉,想要跳出这个平台,但发现如果离开这个平台,自己可能什么都不是。


技术思维给程序员带来的影响还在逐渐增大, 当引以为傲的技能逐渐被AI替代,我们需要训练自己的信息思维。


你可以想见克服这两个偏见并不容易,而这也是我们的机会。


pexels-merve-cakir-351055068-15002639.jpg


提供路径


我在刚工作的前几年,特别羡慕那些看起来天生就适合职场的人,工作中不但经常拿到成绩,还能快速晋升。我试图总结他们的经验,是他们认真负责,还是说善于沟通,甚至是擅长和领导搞好关系?


后来我发现,他们有一个关键特质是——好奇心。


比如你遇见程序框架的一个问题,有些人google一下,对着教程修改一下配置,调好了就不管了。有的人偏偏一步步debug源码,直到确定问题的根本原因在哪里。


当开发了一个功能和系统,有的人代码提交之后就不管了。而你就想知道需求是谁提出来的,他在现实中遇见了什么问题,我们的功能昨晚最后解决了吗?


94岁的巴菲特,为什么还能够保持思维的敏捷。凭什么?前一阵子在伯克希尔哈撒韦的股东大会上,他在回答一个13岁孩子提问时,巴菲特说出了自己的答案:好奇心。


他们真诚的关心别人都在想什么,在做什么,愿意接纳不同的视角。他们做的这些事情不是为了获得什么,只是单纯的想知道而已。


当然现在信息这么多,光有好奇还不够,还得思考的更深入一点,提问的更多一点。


如果你想克服大脑的这两个偏见,有以下几个经验供你参考——


首先理解信息是跟人连接在一起的。很多知识或者道理,不只是纸面上干巴巴的文字,而都是由现实中的人真实感受和体验。


由于我们的成长环境不同,因此每个人的视角和思维方式都不一样,有些道理你需要放在他那个具体的情境之中才能体会到那句话是什么意思。


1月份DeepSeek R1横空出世,我看网上说全世界的大模型团队都在研究R1的论文。我就去问了问一个做大模型的朋友有没有关注这块,当时临近过年,大家其实都已经在期待放假了。我朋友回答说:“反正领导已经开始研究了,要不然我也不会这么忙,给我平添烦恼。”


这种真实朋友给我的的反馈,让我立刻感受到DeepSeek R1带来的震撼有多么大。


培养对「一手信息」的敏感度


一手信息就是那些还未上网,来自一线的信息。你或许认为现在网络这么发达,想了解任何事情都可以从网上找到答案,并且AI能力突飞猛进,把信息交给AI,那么AI就可以帮我们做任何事。


但实际上这个世界上永远存在那些仅存在于一线,还未上网的「隐性知识」。书本会告诉你“是什么”和“为什么”,而实际接触一线,我们才知道很多事情是如何发生的。


刘润老师在最近的文章里分享了他进二十多年,坚持在做的一件事情就是「参访」。每年平均的出差时间有上百天,只要有机会就会去现场看一看,刘润老师在文章中描述的很清晰,在办公室看报告、打电话,和你去生产线走一走,和一线员工聊几句的差别是非常大的。


最有意思的一个描述是一家企业员工的眼神、办公室的氛围,甚至厕所干不干净,这些细节都会藏着关于公司的文化、管理的密码。


训练自己跨界翻译的能力。


跨界翻译你能不能把一个领域的信息,用另一个领域的语言表达出来,让别人能听懂。


也许在程序员和产品经理为了一个问题争论的面红耳赤的时候,你是否能有一种更好的方式,让产品经理能听懂工程师的技术方案是什么?是否能让工程师明白,真实的用户需求是什么?


比如有一次销售很着急的来找研发说:“我们有一个大客户说下周前必须研发出这个功能,不然就不验收!”


研发同事一听,满脸不屑地说:“你知不知道这个功能要重构整个接口?开发的工作量非常大,下周根本不可能。客户表述清楚了吗,还是你自己拍脑袋定的?”


销售和研发直接氛围一度陷入紧张,但是跨界翻译者可能会这么说:



销售最在意的就是验收,因为这决定了他是否能拿到这家客户的收入。研发在意的是技术稳定性,贸然增加新功能也是“挖坑”。


我们不妨看看客户为什么需要这个功能,我们系统有没有满足部分功能的方案先应急,而不是按照客户要求全部重新开发?



这需要大量的学习、消化和吸收,你只有见过和积累的足够多,才能够做到触类旁通,举一反三。


说在最后


真正限制我们的,从来不是技术,而是视野。信息思维并不是让你放弃技术,而是让你站得更高,看得更远,理解得更深。


你看到的世界有多宽,你未来的上限就有多高。


不知道这篇文章能否对你有所启发,又或者你能想到身边的哪个朋友可能会从中受益呢?


这是东东拿铁的第78篇原创文章,欢迎关注。


作者:东东拿铁
来源:juejin.cn/post/7503712510592385051
收起阅读 »

30岁了才有了自己的博客

写作是很痛苦说来惭愧,干程序员这么多年,30 岁了,终于想起来要自己搭建一个博客了!其实一直羡慕别人拥有炫酷的博客,可是自己却一直没去做。作为前端程序员,通常来说,搭建好看的博客还是非常容易的,不过因为自己没啥分享欲望,加上上学时对写作的厌烦(上学时,语文不及...
继续阅读 »

写作是很痛苦

说来惭愧,干程序员这么多年,30 岁了,终于想起来要自己搭建一个博客了!其实一直羡慕别人拥有炫酷的博客,可是自己却一直没去做。作为前端程序员,通常来说,搭建好看的博客还是非常容易的,不过因为自己没啥分享欲望,加上上学时对写作的厌烦(上学时,语文不及格的主要原因就是作文)。

为什么现在想起来搭建博客呢?

我发现,我虽然不喜欢写作,却喜欢记录,学习笔记、工作总结、快捷命令汇总等等。学习新技术时,我喜欢把教程或者书本上的语言总结成自己能看懂的语言记录起来,然后看看自己的记事本,这么多年来也有 600 多篇了。

因此,我觉得我不是不喜欢写东西,而是我内心对写作的的恐惧,也担心自己水平有限,文章不够深入,误人子弟。也是为什么我一直不敢把自己写的东西发布到网上。

[质问] 那么,为啥你现在敢发了,你水平更高了?还是你写作水平提升了??

[回答] 其实都不是!回想有一天,发现我多年前发布的第一篇文章,竟然现在都还有人收藏点赞,全文不过 500字,当时 md 语法都不知道,更别谈什么排版了。

这让我意识到一个问题:即便随手写的一篇文章,只要有完整的解决方案,都有可能帮助到别人

我掘金的第一篇文章。

当然,除了帮助别人,分享文章还有有什么好处呢?会获得点赞和评论;甚至会遇到一些志同道合的人加好友,一起聊技术细节。当然,对于淡泊名利的你来说,这些有什么用呢?这些东西都是正反馈的来源呀!!!

正反馈

说到正反馈,这真的是一个值得深入的话题。工作中,大多数时候的任务是重复和无聊的,你的正反馈来源多数是你的上级或者同事,可是这样的正反馈是很少的。生活中也是一样。也就导致对工作失去兴趣,对技术失去兴趣,因为没有正反馈,也就没有动力继续,不想做任何事情。所以我们需要主动去寻找一些能产生正反馈的事情,写文章、运动、学习,分享。都可以。(有段时间,我每天上班第一件事就是看看有没有新的点赞和评论。)

其实这些道理一早就知道,很多文章、前辈都有说过,可是呢,人呀,就是要自己亲身体会后才会明白!

开始写作

与其说是开始写作,不如说是开始记录,对我来说更加合适。我并不擅长写出段落清晰、用词优美的文章。所以我决定把写作当做生活中的记录,把本地的总结记录分享到线上论坛。

既然要分享到网上,也促使我要求自己发布的文章不仅是自己能看懂,尽量也能让所有人看懂。这很重要!!!

让所有人能看懂很重要,因为即便是自己写的文章,隔一段时间你回头看,会发现啥也看不懂了,根本回想不起来当时是怎么实现的。这就是因为当时写得不够清晰。

于是,我逐渐将本地的记录文章颁发到了论坛,并获得了一些收获。

当然,这点数据根本不够看。对我来说是一个开始,打破固有思维的开始!渐渐地,我从一年 5 篇,到一年 10 篇了,现在一个月一篇。发布的文章逐渐变多了... 这可并不是我强迫自己输出呀(不可能,我意志力不强),这本来就是我本地记录的频率。

这也是我的做事风格,把一些看似很难的事情变得平常化。例如记单词,地铁上就非常适合记单词,手机没网络,记完单词刚好就到公司了。

写本篇的时候,我发现又有一段时间没更新了,不是我没写,是写了很多,都还没发布,因为总觉得少点什么。

搭建博客

说了这么多,总算可以回归正题了~

我参考了 v 友们的建议想搭建自己的博客,求大佬们推荐方案 - V2EX,总结出以下常见的博客框架。

  • wordpress
  • hugo
  • hexo
  • Astro
  • typecho

不过,看了一圈,都不太适合我,要么是配置麻烦、要么主题不好看。相反,并不是这些博客不好,里面的插件、主题多得很,只是没有找到我想要的那种风格(喜欢折腾0.0),下面我会详细解释。

我喜欢的风格

之前我一直很长一段时间,我很喜欢那种酷炫的博客,例如,动态背景图(雪花、3D 地图),或者页面下方还有个可以通过鼠标挑逗的二次元卡通人。再就是搞一些炫酷跳动文字?大家应该都懂,哈哈。

而现在呢,我想要的博客就是:

”简约“

看了太多混杂广告、推广、链接的博客,我更想让读者专注在文章本身上。所以除了文章相关的内容,其他东西一律去除。

”简单“

博客要关注的是内容,所以发布流程越简单越好,我只需要关注写内容就好了。

结合这两点,并简单调研了下相关实现,还是决定自己搭建一个,比较往后较长一段时间都要用它,所以还是自己用着舒服为主。

页面展示

Github: github.com/chennlang/c…

PC 端

H5 端

样式参考了以下两个非常喜欢的博主。

NextJs 搭建博客

其实博客的本质,无非就是一个 markdown 的渲染器,对于前端来说,实现起来不算难事。所以我决定使用 NextJs 自己搭建一个,选用 Nextjs 的主要是因为它天然对 SSG (静态生成)的友好支持。

1.配置 nextConfig

通过如下配置,我们就可以导出一个静态web项目。

const nextConfig: NextConfig = {
/* config options here */
trailingSlash: true,
output: 'export',
};

2. 文章格式范式

我们将文章放在 posts 目录下,文章格式如下:

---
title: "时隔三年,一个可视化可交互的前端依赖分析工具发布了"
date: "2025-02-01"
categories: "Life"
summary: "我一直认为它只是一个不完美的半成品,所以我只是悄悄的上架到了个人的 github 仓库,并没打算公之于众。不过就在今天,我意外的发现仓库多了一个陌生人的 Issue,真的很震惊,我没想到真的有人安装文档安装使用了。这真的让我感到意外,也许真的有人觉得有用,那么我就要做好它,也有责任做好它!"
---


### 终于有勇气发布了~
我一直认为它只是一个不完美的半成品,所以我只是悄悄的上架到了个人的 github 仓库,并没打算公之于众。不过就在今天,我意外的发现仓库多了一个陌生人的 Issue,真的很震惊,我没想到真的有人安装文档安装使用了。这真的让我感到意外,也许真的有人觉得有用,那么我就要做好它,也有责任做好它!

3. 解析文章内容-核心逻辑

import { promises as fs } from "fs";
import path from "path";
import matter from "gray-matter";
import { remark } from "remark";
import html from "remark-html";

// 获取文章内容
export async function getPost(id: string) {
const markdownWithMeta = await fs.readFile(
path.join("posts", id + ".md"),
"utf-8"
);
// frontmatter 是文章的元数据信息, content 是文章内容
const { data: frontmatter, content } = matter(markdownWithMeta);

const processedContent = await remark().use(html).process(content);
const contentHtml = processedContent.toString();

frontmatter.categories = Array.isArray(frontmatter.categories) ? frontmatter.categories : [frontmatter.categories || "Default"]

return {
id,
contentHtml,
frontmatter,
}
}

4. 展示文章页面-核心逻辑

const Post = async ({ params }: any) => {
const { frontmatter, contentHtml } = await getPost(params.id);

return <div>
<h1 className="text-2xl mb-4 font-bold">{frontmatter.title}h1>
{/* 元数据 */}
<p className="flex flex-wrap">
{metaList.map((item) => (
<span key={item.label} className="text-gray-600 mr-4">
<label>{item.label}: label> {item.value}
span>
))}
p>
{/* 内容 */}
<div className="mt-4" dangerouslySetInnerHTML={{ __html: contentHtml }} />
<div className="mt-10">
<Comments />
div>
div>
};

展示就很简单了 dangerouslySetInnerHTML 将内容渲染在页面上就好了

5. 添加评论功能

因为是静态页面,所以就不存在数据库和server服务,所以最佳的方式是直接使用 giscus

利用 GitHub Discussions 实现的评论系统,让访客借助 GitHub 在你的网站上留下评论和反应吧!本项目深受 utterances 的启发。

首先我们到 giscus 上配置好我们的 github 项目,并在项目中开启 GitHub Discussions 功能。

所以本质上,所有评论最终都存在该仓库的 Discussions 里,每个文章对应一个 discussion。

对应关系可以自行设置,默认是文章的 url 路径对应作为 discussion 的标题,然后该文章的评论都是在这个 discussion 下。

然后新建一个 Comments 组件(配置需要根据自己的仓库自行修改)

"use client";

import Giscus from "@giscus/react";

export default function Comments() {
return (
<Giscus
repo="xx/xxx.github.io"
repoId="xxxx"
category="xxx"
categoryId="xxxx"
mapping="pathname"
strict="0"
reactionsEnabled="1"
emitMetadata="0"
inputPosition="top"
theme="preferred_color_scheme"
lang="zh-CN"
/>

);
}

注意:

  1. 本地 localhost 域名可能不会自动创建 discussion,发布到线上后就能解决。
  2. 自动创建Discussion的触发条件是:当用户首次在该页面发表评论或表情时才会创建。若未进行任何交互,Discussion不会自动生成。

Github Page 部署

既然输出是静态页面,可以托管的地方就很多了,前面我也提到了,我并不想做除了写内容以外的任何事,Github Page 就是很不错的选择,不仅能托管文章代码,还能配合流水线自动构建,一举两得。

  1. 创建仓库

新建一个 [用户名].github.io 的 Github 仓库

  1. 新建一个 nextjs 部署构建流水线 .github/workflows/nextjs.yml
# Sample workflow for building and deploying a Next.js site to GitHub Pages
name: Deploy Next.js site to Pages

on:
push:
branches: ["main"]
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: 'npm'

- name: Install pnpm
run: npm install -g pnpm

- name: Detect package manager
id: detect-package-manager
run: |
if [ -f "${{ github.workspace }}/yarn.lock" ]; then
echo "manager=yarn" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=yarn" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/pnpm-lock.yaml" ]; then
echo "manager=pnpm" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=pnpm" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/package.json" ]; then
echo "manager=npm" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=npm" >> $GITHUB_OUTPUT
exit 0
else
echo "Unable to determine package manager"
exit 1
fi

- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}

- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./out

deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

然后当 main 分支 push 时自动触发 NextJs 项目的构建,完成 GitHub Pages 页面部署。接下来你就可以通过 [usename].github.io 访问属于你自己的博客了!

总结

最后,如果有和我一样喜欢折腾的小伙伴,可以使用使用我的项目作为模版,搭建一个属于你自己的博客。当然,如果你觉得还不错的话,别忘了留下你的 star~ GitHub - chennlang/chennlang.github.io: blog


作者:Alang
来源:juejin.cn/post/7474923858165252105

收起阅读 »

iOS、Android、Flutter 流行框架对比(基于 OpenAI 的数据)

背景 基于 OpenAI 最新的 o1-preview 模型,整理出来的 App 分别使用 iOS、Android、Flutter 流行框架对比,方便查阅,部分数据可能不完全准确,整体的数据质量我看了一下还是挺高,有需要的自取。 内容 自动布局的框架 iOS...
继续阅读 »

背景


基于 OpenAI 最新的 o1-preview 模型,整理出来的 App 分别使用 iOS、Android、Flutter 流行框架对比,方便查阅,部分数据可能不完全准确,整体的数据质量我看了一下还是挺高,有需要的自取。



内容


自动布局的框架


iOS



Prompt: 以表格的形式输出 iOS 自动布局框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
Auto LayoutSwift/Objective-CiOS 原生的布局系统动态适应不同屏幕尺寸的布局N/A(原生功能)N/A
SnapKitSwift简化 Auto Layout 的 DSL使用链式语法创建布局约束SnapKit19k+
MasonryObjective-C类似 SnapKit 的 Objective-C 版本使用链式语法创建 Auto Layout 约束Masonry18k+
PureLayoutSwift/Objective-C提供一致的 Auto Layout 接口简化约束的创建和管理PureLayout7k+
CartographySwift使用纯 Swift 语法构建 Auto Layout通过操作符重载简化约束定义Cartography7k+
TinyConstraintsSwift轻量级的 Auto Layout 语法糖更简洁地创建和管理约束TinyConstraints3k+
SteviaSwift简洁的布局框架使用声明式语法定义布局Stevia3k+
EasyPeasySwift简化 Auto Layout 语法的库使用简洁的语法定义和修改约束EasyPeasy2k+
AnchorageSwift提供更简洁的 Auto Layout API利用 Swift 特性简化约束定义Anchorage1k+
LayoutKitSwift高性能的布局框架使用纯代码创建高性能的视图布局LayoutKit7k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


Andorid



Porompt:以表格的形式输出 Andorid 自动布局框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
ConstraintLayoutJava/Kotlin官方提供的强大布局系统创建复杂布局,支持动画和约束N/A(原生功能)N/A
FlexboxLayoutJava/Kotlin类似于 CSS Flexbox 的布局库实现灵活的响应式布局FlexboxLayout6k+
MotionLayoutJava/Kotlin基于 ConstraintLayout 的动画布局系统创建复杂的过渡和动画N/A(原生功能)N/A
AndroidAutoLayoutJava自动适配各种屏幕尺寸的布局库根据屏幕尺寸自动调整布局参数AndroidAutoLayout10k+
Anko LayoutsKotlin使用 Kotlin DSL 构建布局简化布局代码,减少 XML 文件Anko15k+
FlowLayoutJava支持自动换行的布局适用于标签、按钮等需要自动换行的场景FlowLayout9k+
PercentLayoutJava/Kotlin支持百分比布局的库(已弃用)根据父布局的百分比设置子视图尺寸PercentLayoutN/A
EpoxyJava/KotlinAirbnb 开源的用于构建复杂列表的库声明式界面,支持复杂布局和模型Epoxy11k+
Gr0upieJava/Kotlin简化 RecyclerView 布局和适配器的库轻松创建复杂的列表布局Gr0upie12k+
DataBindingJava/Kotlin官方的数据绑定库将布局与数据源绑定,减少代码量N/A(原生功能)N/A

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


Flutter



Porompt:以表格的形式输出 Flutter 自动布局框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
Flutter 内置布局系统DartFlutter 自带的布局系统,包含多种布局组件提供灵活的布局,支持多种布局方式N/A(原生功能)N/A
Responsive FrameworkDart响应式布局框架自动适配不同屏幕尺寸和分辨率Responsive Framework2k+
flutter_layout_gridDart类似于 CSS Grid 的布局库支持基于网格的布局方式flutter_layout_grid1k+
flutter_staggered_grid_viewDart创建不规则网格布局的库支持瀑布流布局和不规则网格布局flutter_staggered_grid_view2.5k+
AutoSizeTextDart自动调整文本大小的组件根据可用空间自动调整文本大小AutoSizeText1.5k+
flutter_screenutilDart屏幕适配解决方案支持多屏幕尺寸、像素密度的适配flutter_screenutil5k+
SizerDart使响应式设计变得简单的库根据屏幕尺寸调整组件和字体大小Sizer600+
flutter_responsiveDart响应式布局助手简化不同屏幕尺寸的布局适配flutter_responsive300+
align_positionedDart更灵活的 Positioned 小部件提供百分比定位和对齐align_positioned200+
FlowBuilderDart用于构建响应式和可组合的布局提供灵活的流式布局FlowBuilder1k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


网络请求的框架


iOS



Prompt: 以表格的形式输出 iOS 网络请求框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
AlamofireSwift强大的网络请求库,简化 HTTP 网络请求支持链式调用、文件上传下载、认证处理Alamofire40k+
AFNetworkingObjective-C功能强大的网络请求库,支持多种网络请求支持数据任务、上传、下载、认证处理AFNetworking33k+
SwiftyJSONSwift简单的 JSON 解析库轻松解析和处理网络请求中的 JSON 数据SwiftyJSON22k+
KingfisherSwift强大的图片下载和缓存库支持异步图片下载和缓存,集成到网络请求Kingfisher22k+
PromiseKitSwift处理异步操作的 Promise 库简化异步网络请求、支持链式调用PromiseKit14k+
MoyaSwift基于 Alamofire 的网络请求抽象层通过 API 定义和管理网络请求,插件支持Moya15k+
Reachability.swiftSwift用于监控网络连接状态的库支持监控网络状态,处理连接状态的变化Reachability.swift12k+
URLSessionSwiftiOS 原生网络请求 API完全支持 HTTP 和 HTTPS 请求N/A (原生功能)N/A
SiestaSwift高级网络请求框架,支持缓存和状态管理支持响应式编程、数据缓存、重试机制Siesta3.5k+
NetworkingSwift网络请求简化库,支持上传下载和缓存文件上传下载、自动管理缓存Networking1.1k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


Andorid



Prompt: 以表格的形式输出 Andorid 网络请求框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
RetrofitJava/Kotlin类型安全的 HTTP 客户端,用于 Android 和 Java简化 RESTful API 的网络请求,支持异步和同步Retrofit42k+
OkHttpJava/Kotlin高效的 HTTP 和 HTTP/2 客户端支持连接池、拦截器和超时设置等高级特性OkHttp43k+
RxJavaJava/Kotlin用于异步和事件驱动编程的响应式扩展库支持异步数据流处理,可与网络请求结合使用RxJava47k+
KtorKotlinKotlin 的异步网络框架,支持客户端和服务器端支持多种协议,异步编程,协程支持Ktor12k+
AsyncHttpClientJava异步的 HTTP 客户端支持异步网络请求、文件上传下载AsyncHttpClient10k+
VolleyJavaGoogle 提供的网络请求库支持异步请求、图片加载和缓存内置于 Android(无需单独的 GitHub 仓库)N/A
FuelKotlin轻量级的网络请求库简化 HTTP 请求,支持并发和协程Fuel4k+
IonJavaAndroid 上的异步网络请求和图片加载库支持异步请求、图片加载、缓存Ion7k+
FastAndroidNetworkingJava基于 OkHttp 的高性能网络库支持文件上传下载、JSON 解析、缓存FastAndroidNetworking5k+
Apollo AndroidJava/Kotlin用于 Android 的 GraphQL 客户端支持类型安全的 GraphQL 请求和响应处理Apollo Android5k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 9 月。如需获取最新信息,请访问相应的 GitHub 仓库。


Flutter



Prompt: 以表格的形式输出 Flutter 网络请求框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
httpDartFlutter 和 Dart 的基本 HTTP 客户端简单的网络请求支持,GET/POST 等方法http1.5k+
DioDart功能强大的 HTTP 客户端库支持拦截器、全局配置、FormData、请求取消Dio13k+
ChopperDartRESTful API 客户端库,类似 Retrofit支持代码生成、拦截器、内置 JSON 解析Chopper1.6k+
Retrofit.dartDartRetrofit 的 Dart 实现自动生成 API 调用代码,支持 RxDartretrofit.dart1.8k+
graphql_flutterDartGraphQL 客户端库支持查询、变更、订阅和缓存graphql_flutter3.5k+
Flutter Socket.IODartSocket.IO 的 Flutter 客户端实现实时通信,支持 WebSocketsocket_io_client600+
Flutter Secure StorageDart安全的密钥/值存储库用于存储令牌和敏感信息flutter_secure_storage1.7k+
Flutter DataDart数据管理和网络请求框架支持关联、缓存、离线支持flutter_data700+
GetConnectDartGetX 框架内置的网络请求库简化网络请求,集成状态管理GetX9k+
FlutterFireDartFirebase 的 Flutter 插件支持实时数据库、身份验证、云功能等FlutterFire7k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


图片加载的框架


iOS



Prompt: 以表格的形式输出 iOS 网络图片加载框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
SDWebImageObjective-C/Swift高性能的异步图片加载和缓存框架支持 GIF、WebP、APNG、缩略图等格式SDWebImage24k+
KingfisherSwift纯 Swift 实现的轻量级图片加载框架支持异步下载、缓存和处理图片Kingfisher21k+
NukeSwift功能丰富的图片加载和缓存框架支持异步加载、缓存、预加载等功能Nuke7k+
PINRemoteImageObjective-C/Swift高性能的图片加载和缓存库支持异步下载、缓存、支持 WebP 格式PINRemoteImage6k+
AlamofireImageSwift基于 Alamofire 的图片组件库支持图像过滤、缓存和下载AlamofireImage4k+
YYWebImageObjective-C高性能的异步图片加载和缓存框架支持 GIF、APNG、WebP、缩略图等格式YYWebImage4k+
HanekeSwiftSwift轻量级的缓存库,支持图片缓存支持内存和磁盘缓存,自动缩放图片HanekeSwift5k+
SDWebImageSVGKit PluginObjective-C/SwiftSDWebImage 的 SVG 支持插件支持加载和显示 SVG 格式图片SDWebImageSVGCoder300+
UIImageView+AFNetworkingObjective-CAFNetworking 的 UIImageView 类别为 UIImageView 提供异步图片加载UIImageView+AFNetworking33k+ (AFNetworking)
ImageLoaderSwiftSwift简单的图片加载和缓存库支持异步加载、缓存和占位图ImageLoaderSwift1k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


Andorid



Prompt: 以表格的形式输出 Andorid 网络图片加载框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
GlideJava/Kotlin高效的图片加载和缓存库支持异步加载、内存和磁盘缓存、GIF 支持Glide34k+
PicassoJava简单强大的图片下载和缓存库处理图片加载、缓存,支持转换和裁剪Picasso19k+
FrescoJavaFacebook 开源的图片库支持大图加载、GIF、WebP、渐进式加载Fresco18k+
CoilKotlin基于 Kotlin 的现代图片加载库支持异步加载、内存和磁盘缓存、动画Coil9k+
Universal Image LoaderJava过时但曾经流行的图片加载库支持异步加载和缓存Universal Image Loader16k+
Glide TransformationsJavaGlide 的图像转换工具集合提供多种图像转换效果Glide Transformations10k+
Picasso TransformationsJavaPicasso 的图像转换工具集合提供多种图像转换效果Picasso Transformations5k+
AndroidSVGJava支持加载 SVG 矢量图的库解析和渲染 SVG 文件AndroidSVG2k+
Subsampling Scale Image ViewJava支持显示超大图片的控件支持平滑缩放和拖动大尺寸图像Subsampling Scale Image View8k+
ImageLoaderJava轻量级的图片加载库支持异步加载和缓存ImageLoader16k+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 10 月。如需获取最新信息,请访问相应的 GitHub 仓库。


Flutter



Prompt: 以表格的形式输出 Flutter 网络图片加载框架,包括使用的编程语言、描述、功能、GitHub 仓库地址和 Star 数量



框架/库名称编程语言描述功能GitHub 仓库地址Star 数量
cached_network_imageDartFlutter 的缓存网络图片加载库支持图片缓存、占位符、错误图片显示等cached_network_image5k+
flutter_svgDartSVG 矢量图支持库加载和渲染 SVG 格式的矢量图flutter_svg3k+
photo_viewDart图片查看组件支持图片缩放、平移,适用于图片预览photo_view1.6k+
extended_imageDart功能丰富的图片加载和处理库支持缓存、编辑、裁剪、旋转等高级功能extended_image1.5k+
flutter_advanced_networkimageDart高级网络图片加载库支持缓存、加载进度指示、重试机制等flutter_advanced_networkimage800+
octo_imageDart提供多种占位符和淡入效果的图片加载库支持占位符、淡入淡出动画、错误重试octo_image500+
flutter_blurhashDart显示模糊占位符的库支持使用 BlurHash 占位符,提高加载体验flutter_blurhash500+
progressive_imageDart渐进式图片加载库支持先加载低分辨率图像,后加载高清图像progressive_image200+
flutter_lubanDart图片压缩库实现了鲁班算法的图片压缩flutter_luban500+
flutter_advanced_networkimageDart高级网络图片加载库支持缓存、加载进度指示、重试机制等flutter_advanced_networkimage800+

请注意,Star 数量可能会随着时间变化,以上数据截至 2023 年 9 月。如需获取最新信息,请访问相应的 GitHub 仓库。


数据洞察


针对文档内容,我将分别为 iOS、Android 和 Flutter 提供一些有价值的观点,基于框架的特性、开发趋势及其在各自生态系统中的重要性。


iOS 平台的分析



  1. 自动布局系统(Auto Layout 与替代方案) :



    1. Auto Layout 是 iOS 的原生布局系统,它的动态布局功能使得 iOS 应用能够很好地适配各种设备的屏幕尺寸。随着新设备的推出,开发者需要确保应用的界面能在不同屏幕上保持一致,Auto Layout 提供了很好的适配解决方案。

    2. 但是,由于 Auto Layout 语法相对繁琐,开发者更倾向于使用第三方库来简化布局创建,例如 SnapKit(19k+ stars)和 Masonry(18k+ stars)。这些库通过链式语法让布局的书写更具可读性,提升了开发效率。



  2. 网络请求的主流选择:



    1. Alamofire(40k+ stars)是 iOS 开发中最受欢迎的网络请求框架,它简化了 HTTP 请求,支持文件上传、下载及认证处理。它的链式语法大大提高了网络请求的简洁性和可读性,因此广泛应用于项目中。

    2. 对于 Objective-C 开发者,AFNetworking(33k+ stars)依然是稳固的选择,尽管 Swift 逐渐成为主流编程语言,AFNetworking 仍在老项目维护和过渡期间使用。



  3. 图片加载和缓存技术:



    1. SDWebImage(24k+ stars)和 Kingfisher(21k+ stars)是 iOS 中最常用的异步图片加载和缓存库。两者支持图片的异步下载、缓存和格式处理,尤其适合优化应用的性能并提升用户体验。




Android 平台的分析



  1. 布局系统的灵活性:



    1. Android 的官方布局工具 ConstraintLayout 是目前最强大的布局系统,支持复杂的布局和动画。它结合了 MotionLayout 等工具,让开发者能够轻松实现 UI 动效,这一点在高交互性应用中至关重要。

    2. 另一个重要的布局库是 FlexboxLayout,它借鉴了前端开发中 CSS 的布局方式,使得 Android 开发者可以使用响应式设计来适配多种屏幕尺寸和分辨率。



  2. 网络请求的多样化选择:



    1. Retrofit(42k+ stars)和 OkHttp(43k+ stars)是 Android 社区中最受欢迎的网络请求库。Retrofit 简化了 API 定义和请求处理,尤其适合 RESTful API 的集成;而 OkHttp 则因其高效的 HTTP/HTTP2 支持和先进的特性如连接池、超时机制等,成为高性能应用的首选。



  3. 图片加载技术:



    1. Glide(34k+ stars)和 Picasso(19k+ stars)是 Android 开发者的常用工具。Glide 提供了更强大的缓存管理和内存优化能力,适合对性能要求较高的应用,而 Picasso 则以简单的 API 接口著称。




Flutter 平台的分析



  1. 响应式布局的优势:



    1. Flutter 的内置布局系统提供了丰富的布局组件,可以轻松实现不同屏幕的适配。结合 Responsive Framework(2k+ stars)等框架,开发者能够快速构建适应各种屏幕尺寸的应用,确保跨平台应用的 UI 一致性。



  2. Dart 语言和网络请求框架:



    1. Dio(13k+ stars)是 Flutter 社区的主流 HTTP 客户端库,支持全局配置、拦截器、请求取消等高级特性,非常适合复杂网络请求场景。其功能与 Android 的 Retrofit 类似,但通过 Dart 实现,与 Flutter 的生态系统紧密结合。



  3. 图片加载的灵活性:



    1. cached_network_image(5k+ stars)是 Flutter 中最受欢迎的图片加载库,支持缓存和占位符功能,这在跨平台应用中有助于提升用户体验,尤其是在网络环境不稳定的情况下。




总结



  • iOS 开发者在布局时普遍依赖 Auto Layout,但为了简化布局代码,越来越多开发者选择 SnapKitMasonry 等第三方库。网络请求和图片加载方面,AlamofireSDWebImage 占据主导地位。

  • Android 开发在布局上具有更多选择,尤其是 ConstraintLayoutFlexboxLayout,这两者提供了极大的灵活性。网络请求方面,RetrofitOkHttp 继续主导市场,而 Glide 则成为处理图片的首选库。

  • Flutter 由于其跨平台特性,布局和网络请求框架都高度依赖于 Dart。Diocached_network_image 是最受开发者青睐的选择,特别是在需要处理多屏幕适配和网络资源加载的场景中。


通过这些框架的对比,可以更好地理解不同平台开发的趋势和工具的选择,为优化项目开发流程提供有力支持。


作者:wangruofeng
来源:juejin.cn/post/7430770689684865078
收起阅读 »

我在成都教人用Flutter写TDD(上)——为啥要搞TDD?

哈喽,我是老刘 写这篇文章的时候刚回到北京,之前的一周去成都帮助一家公司完成基于Flutter的TDD流程的搭建。 这个工作一半是敏捷教练,一半是Flutter相关的技术顾问。 起因是这个客户接了一份欧洲那边的开发项目,但是欧洲客户对项目流程的要求比较高,要求...
继续阅读 »

哈喽,我是老刘


写这篇文章的时候刚回到北京,之前的一周去成都帮助一家公司完成基于Flutter的TDD流程的搭建。

这个工作一半是敏捷教练,一半是Flutter相关的技术顾问。

起因是这个客户接了一份欧洲那边的开发项目,但是欧洲客户对项目流程的要求比较高,要求开发团队采用TDD流程。

这是老刘第二次碰到要求开发采用TDD的情况,而且都是欧美客户。

为啥欧美软件开发团队对TDD这样的敏捷开发趋之若鹜,而大多数国内团队却鲜少能真正搞起来敏捷开发?

是我们比欧美开发者更务实还是敏捷开发确有其独到之处?

老刘希望用这篇文章尝试解答一下。

image.png
我记得刚去成都的时候大家一起吃饭,讨论起啥样的项目适合TDD,TDD会不会浪费额外的时间这些话题。

当时吃饭只是简单的聊了聊,但是让我意识到一个问题,TDD或者说敏捷开发在国内之所以一直没有真正成为主流更多的可能是意识问题。

看不到明确的收益,却能看到明确的额外工作量,怪不得众多管理者不愿意尝试。

这篇文章会回顾一下我的敏捷开发相关的经历,并借此尝试回答TDD究竟能给我们的开发带来什么收益。


初试敏捷:网络安全领域的尝试


老刘我带着团队使用Flutter进行App开发已经6年多了,而搞TDD的时间更长一些。

大约10多年前我还没有做客户端开发的时候,那时候我是做网络安全方面开发的,使用的是C语言。

那时候公司希望在敏捷开发方面做一些尝试,因为我在研究生期间做过一些敏捷方面的工作,所以就承担起来这个任务的研发部分。

当时公司希望尝试的是Scrum的完整流程,但是因为涉及到的团队和部门有点多,而很多团队对这个流程是持保留意见的,所以最终就没有搞成。

image.png
但是研发内部的单元测试和TDD流程因为只涉及开发团队,最终得以保留,这成为了我们探索敏捷开发的重要起点。


TDD的实践与收获


虽然最终Scrum没有成功搞起来,谈不上升职加薪 ┭┮﹏┭┮

不过在TDD的探索方面确实有很多的收获:


1、实战经验的积累


这是我第一次在百万级代码量以及几十人的项目中实施TDD流程。

相当于把以前只能算是纸上谈兵的认知变成了真正的实战经验。


2、踩坑与成长


在整个的实践过程中,我们几乎踩遍了所有可能的“坑”。

要知道防火墙项目的规模和复杂度相对于一般客户端或者服务端项目要高很多,特别是还有很多底层数据的操作和对系统内核的修改定制。

例如,我们的代码需要在MIPS架构的CPU上运行,而MIPS与常见的x86架构在字节序上存在差异。这种差异导致我们在PC端进行单元测试时,经常遇到与设备上运行时不同的错误。

image.png
这件事直接导致了后来我们对整个代码进行重构,把我们的业务逻辑和cpu架构解耦。

这是我第一次如此直观且深刻的看到架构到底是什么,也让我在后续的开发过程中开始有意识的注意架构设计的合理性。


3、TDD与架构合理性


在解决TDD实践中遇到的各种问题时,我们逐渐意识到,超过一半的问题实际上源于不合理的架构设计。

以之前提到的CPU字节序问题为例,一个合理的架构设计应该将底层数据操作与上层业务逻辑解耦。

理论上,我们都明白低耦合、高内聚的重要性,但在实际操作中,很难把握到何种程度才算真正实现。

而单元测试在这里就扮演了一个标尺的角色。

它通过测试的难易程度和可行性,帮助我们检验架构设计的合理性。

如果某个部分难以测试或者无法测试,这往往意味着架构存在问题。

通过这种方式,TDD不仅促进了代码质量的提升,也推动了架构设计的不断优化。

对TDD的推行加深了我们对架构合理性的理解,也让我们在后续的项目中能够更加注重架构的合理设计。


4、TDD是思维模式的转变


自己用TDD方式写代码和组织大家一起写又是一种不同的经验。

TDD本质上不是一个编码流程,而是一个设计流程。

在工作中去观察那些真正的资深程序员和新手的差别就会发现,资深程序员是在做脑力劳动,新手是在做体力劳动。
image.png
资深程序员通常是把一个功能点的逻辑链条想清楚才开始动手写,而新手却往往急于动手,发现问题后才不得不对代码做大幅的修改。

所以他们不是在加班写代码就是在加班改bug,然后就把工时卷上去了。

TDD为普通程序员提供了一条追赶资深程序员的捷径。

通过先编写单元测试,再通过测试驱动来编写正式代码,TDD迫使开发者在编码之前深入思考功能的逻辑链条。

image.png
这种拆解测试例的过程实际上是在进行设计工作,它要求开发者在动手之前就想清楚功能点的代码设计。

即使最初的设计或思考存在问题,TDD的重构步骤也会促使开发者及时发现并解决问题,减少定位问题的成本。

而且,所有的重构和修改都是在测试代码的保护下进行的,这样可以确保修改不会对现有代码造成意外的影响。

因此,TDD不仅仅是工作顺序的改变,它是一种完全不同的思维模型。

这种思维模式的转变对于提升整个团队的开发效率和代码质量都具有深远的影响。

(关于这一点我会在后面的经历中更详细的说明。)


TDD在客户端开发中的尝试


后来我开始转做Android客户端方向的开发工作。

我尝试着在客户端开发中使用TDD流程。

刚开始我以为这会是一件非常简单的事情,因为Android开发是基于Java体系的,而Java生态中有大量单元测试框架可供挑选。

万万没想到的是在Android工程中执行单元测试每次都需要等待漫长的编译过程。

基本上可以理解为执行一个单元测试就需要把整个工程编译一遍。

虽然可以通过Robolectric等库脱离对Android环境和SDK的依赖,但实际效果仍然很不理想。

要知道TDD的核心在于小步快跑,如果每个测试例都需要编译几分钟然后运行,就完全背离了TDD的出发点了。

所以这次在客户端开发中对TDD的尝试以失败告终。


Flutter带来全新的可能


大约六年前,我带领着Android开发团队,我们当时面临着一个挑战:如何解决Android和iOS两个客户端在用户体验上的差异问题,同时还需要摆脱原生项目中历史代码的泥潭。

在寻找跨平台开发框架的过程中,Flutter以其技术优势脱颖而出,但其年轻和缺乏有说服力的案例让我犹豫不决。

最终是Flutter对单元测试的良好支持让我最终下定了决心。

在此之前,我已经放弃了在手机端开发中实施TDD的想法,因为原生单元测试的体验实在令人沮丧。

但当我尝试了Flutter的单元测试后,我意识到TDD在移动开发中还能再抢救一下。

image.png
Flutter的单元测试体验可以用“舒适”来形容。

测试的运行速度达到了秒级,并且在测试场景下对UI组件的支持也非常出色。

这使得TDD从看似不可能的任务变成了一个顺畅且自然的过程。

Flutter的设计考虑到了TDD的场景,并且不仅仅是在小规模项目中,即使在大规模工程中也能实施TDD,这为移动应用开发带来了全新的可能性。


但是TDD在Flutter上的实施过程也不是一帆风顺的,主要挑战来源于两个方面:

首先,团队成员对Flutter的掌握程度不足。

由于团队中的小伙伴们都是Flutter的初学者,他们在对Flutter本身还不够熟悉的情况下尝试执行TDD,遇到了不少技术上的挑战。

其次,长期从事客户端开发的资深程序员在切换到新的开发流程时,似乎比新手更加困难。

这些资深程序员由于多年养成的开发习惯,很难立即适应TDD的模式。

他们习惯于传统的开发流程,对于TDD这种先编写测试用例再编写代码的方式感到不适应。

这种习惯的转变需要时间和实践,才能逐渐适应并掌握TDD的精髓。


面对这些挑战,我们采取了多种措施来促进TDD的实施。例如,组织定期的培训和研讨会,帮助团队成员加深对Flutter的理解,并通过实际案例来演示TDD的实践方法。同时,我们也鼓励资深程序员和新手之间的交流和合作,通过分享经验和教训,共同克服实施TDD过程中的困难。


基于Flutter的TDD带来的改变


经过半年多的学习、尝试以及代码架构的调整,我们从项目数据上看到了一些明显的变化。

首先解释一下之所以用了超过半年的时间,主要是因为我们的项目采用Flutter + 原生的混合开发模式。

刚开始的时候主要以原生代码为主,Flutter用于开发少数不重要的页面进行测试。

验证了Flutter的用户体验和稳定性后,Flutter页面的比例才开始逐步上升,然后Flutter才变为日常开发的主导。

随着Flutter变成日常开发的主要选择,可以看到几个明显的变化。


1、开发效率提升60%


这其中一半是Flutter本身优秀跨平台能力带来的。

只要不涉及原生功能,Flutter基本可以完全覆盖所有需要编写的代码。

从性能和用户体验来说Flutter页面也完全能胜任代替原生。

另外一半效率的提升则来源于TDD。

这主要体现在下面的几点。


2、提交测试后bug减少70%


这个数据其实从不同的维度统计会有不同的结果,我个人倾向于减少的bug比例会更高一些。

举个例子,产品需求写的可能是从家里坐车到全聚德烤鸭店。

开发人员要实现的是走3米到家门口——开门——走5米到电梯——按电梯哪个按钮——出电梯左转——走5米后右转出单元门……

这还只是正常情况,没有考虑如果电梯坏了怎么处理,路上有人放了东西怎么绕开。

开发工作的本质其实就是把所有正常的、异常的可能情况都进行处理。

这个过程中主要会出两种问题:




  • 有些场景没有考虑到,比如没想到路上被堆了箱子需要绕路。

  • 处理流程不达预期,比如考虑了绕路,但是绕路的流程不对,走不到单元门。



我们正常的瀑布流程其实就是开发人员先思考一下整个流程和都有哪些可能情况,这一步是设计阶段,更精细一些的可能还会区分概要设计和详细设计。

然后就是用代码实现这个流程,并且补充每一个细节,这一步就是编码阶段了。

开发完成后研发人员会进行简单的测试,比如验证按照自己的代码能不能走到全聚德。

如果能走到就会认为功能正常把软件交给测试人员进行更详细的测试。

测试人员会测试所有能想到的可能场景,发现某些场景走不到就给开发人员提bug。

image.png


按照这个流程写代码,出现bug是再正常不过的事情了。

主要有几个原因:




  1. 现实情况纷繁复杂,总会有一开始没有预料到的情况发生。甚至有些情况测试同学也没有预料到,只有APP上线了用户使用中发现了才会反馈回来。

  2. 即使有很严格的概要设计、详细设计流程,其精细程度也远远做不到真实代码的精细度。而设计过程越粗放,编码过程中遗漏、出错的概率就越高。

  3. 研发自己测试代码功能相对来说覆盖范围比较小,有些功能自己感觉实现的没问题,但是又没有测试到,只能在测试阶段由测试人员发现。



上面几种情况中第一种其实是无法避免的,而后面两种TDD都可以帮助开发人员最大幅度的降低发生的概率。

前面说了TDD是一个设计流程,它本质上代替的是概要设计和详细设计。

image.png
我们通过把一个功能需求拆分成不同的任务,把一个任务拆分成多个很具体的测试例来进行代码功能的拆分设计。

这种设计精细到什么程度呢?

每一行功能逻辑的代码都有对应的测试例,因为每一行功能代码都是测试例驱动下编写的。

而且TDD从流程上要求先写测试代码,这就强制开发者必须先进行设计层面的思考,然后才能开始编码。

这进一步避免了瀑布流程中省略或者敷衍设计流程,直接进行编码的情况。


接下来说开发者自测覆盖范围有限的问题。

基于TDD编写的代码每一行都是先有测试代码的,可以说每一行功能代码都是测试覆盖的。

可以在大概率上保证功能代码的运行结果和我们预期是一致的。

那种我写了很多代码,一运行结果和我想的完全不一样的情况在TDD中很难出现。


所以最终效果就是使用TDD流程后,我们团队提交测试的项目,总的bug数量大幅降低,测试周期和产品发布周期的稳定也得以保证。


3、交付健壮、可修改的代码


不知道各位看到这里的同学有多少是正在996的。

加班这种事在国内的软件开发领域很常见,这里面当然有即使不忙也要把工时耗够这种无效内卷的加班文化的原因。

但是也确实有很大一部分比例是因为项目进度不达预期导致开发人员不得不加班加点赶进度。

为什么项目总是面临延期的风险呢?

排除了那些管理混乱总是临时插入新需求的团队,瀑布流程本身对项目进度掌控力不足才是罪魁祸首。

做过几年开发的同学可能都碰到过这种情况:

项目刚开始的时候时间并不紧张,开发进度推进到中期发现原本以为很简单的一个对现有代码模块的修改远比想象中复杂。

要么是那坨代码和众多地方耦合,牵一发动全身,根本没法简单修改。

要么是那坨代码根本看不懂,写它的大神早已离职或者被当作大动脉裁掉了。

image.png
你薅秃仅剩的头发,熬夜加班把这部分代码改完,然后发现不是功能不好用就是原先工作正常的模块出问题了。

然后原本正常上下班的项目迭代周期就变成了996。

这种情况反复的发生,于是开发者在预估项目时间时就会增加很多的冗余时间来应对。

项目管理者知道你会预留冗余的时间,要么压缩项目进度,要么时不时的插入临时功能。

最终无效内卷的死循环达成了。


那么TDD能解决这个问题吗?

答案是可以,而且TDD能将这种情况发生的概率降到最低。

其实我们看前面说的场景,本质上就是两个问题,对现有代码“看不懂、改不动”。

先说“看不懂”的问题

TDD中业务代码都是由测试代码驱动生产的。

所以测试例和测试代码本身就是对业务代码最好的说明。

而且这种说明是站在业务代码的使用者角度,会向你展示业务代码是如何被使用的以及各种不同情况下预期的结果是什么。

另一方面,要想实现所有业务代码都基于测试代码产生,测试例的顺序必须是层层递进的。

所以基于测试例的前后顺序也很容易把握业务逻辑的脉络。


再来说“改不动”

当我们面对一团乱麻的代码,即使这份代码就是自己写的,想在上面做些修改也绝非易事。

究其根本还是当初写代码的时候只顾着实现功能,没有腾出手来对代码的合理性做一些优化。

这其实和一个程序员的能力水平关系不大。

我们的大脑本质上是单核cpu,无法同时干两件同类的事情。

比如你没办法一边和人说话一边写邮件。

同样的道理,你也没办法一边思考业务逻辑如何实现一边思考代码结构如何优化。

敏捷开发的先行者们对这种情况有很清晰的认知,所以敏捷开发中队这种情况也有不少很好的应对手段。

而TDD就是其中很有效的一种。

TDD的小步快跑最后一步就是重构。

image.png
它不要求你实现业务逻辑时就把代码结构一并调整完善,而是把重构这个动作放在了实现业务逻辑之后。

这样就可以保证每个步骤只专心的完成一件事。

写测试代码的时候就专心思考业务代码应该提供什么样的功能。

写业务代码的时候就专心思考具体的技术细节如何实现。

重构的时候就专心思考代码结构怎么样更合理更健壮。


把重构作为一个独立步骤的第二个好处是会强制你进行重构的思考。

其实大部分程序员都是有意愿去优化代码结构的。

但是如果碰到项目进度紧急或者代码结构看起来很简单清晰等情况,人的潜意识就会让我们跳过重构这个动作。

这是人脑降低功耗的一种本能行为。

TDD的好处是把这个动作流程化、标准化。走到这一步,不管代码看起来是不是很简单,你都会去想一想有没有可以重构的地方。

即使最后真的没啥可以改动的,你也尽最大可能做到了代码优化。

而且从实际经验来看,很多时候即使看起来很简单的代码,当你专门去思考重构的时候还是会有一些值得修改的地方。


TDD给重构带来的第三个好处是你的重构是在测试代码保护下进行的。

实际工作中开发人员有时候排斥重构一个重要的原因是责任问题。

比如原先代码虽然混乱,但是能正常工作,你重构了结果出现bug,在很多团队里你就要背这个锅。

TDD的特点是大部分代码都是在测试例的覆盖下。

你的重构是否会对现有代码逻辑造成影响跑一遍测试就知道了。

所以我们重构的时候也不用担心把原先好用的功能搞坏了。


同时这种所有代码都在测试保护下的特性,也解决了“改不动”的另一个原因:代码副作用。

这里说的代码副作用是指当我们为了开发新功能对原有代码进行修改时,影响原有功能不能正常运转。

这一点有过团队开发经验的同学应该深有体会。

新功能提交测试了,收到一堆bug都是影响了原先正常的功能。

当然这本质上还是架构不合理、代码混乱的原因。

但是在TDD的场景下,你要修改的代码都在测试代码的保护下,即使架构不合理也不用担心把原先的逻辑改坏了。


4、Flutter与原生代码对比


我们团队使用Flutter一年多之后,已经有几十个页面由原生迁移到Flutter上。

因为在Flutter端采用了TDD流程,对比这些页面的原生代码和Flutter代码,可以明显看出两者的不同。

Flutter代码更为整洁、清晰。

在Flutter代码中几乎找不到大段的重复代码,基本都在重构阶段被消灭了。

而Flutter代码中除了UI布局和底层的三方库封装部分,其他代码都对应的测试覆盖。

直接体现在开发过程中就是当我们同时有Flutter和原生的新需求时,Flutter投入一个人,原生两端各投入一个人,都是1周开发时间。

Flutter提测后bug数量比原生少了70%以上,三天就测试完成可以交付。

而原生端前前后后改了一周bug才勉强达到交付标准。

那段时间原生iOS端的开发同学每天晚上加班改bug到10点多(那个模块iOS端的历史代码太混乱,经常一不小心就把原先的代码改出问题)。

所以不同流程下开发效率的差距可见一斑。

而且这种差距会随着项目迭代,代码量的累积和越来越大。


总结


六年后再来看,我们的App大多数页面都已经切换到Flutter版本。

前段时间领导找我谈心好几次,都是因为我们客户端团队平均工时太少。

可是我们对比另一个产品没有使用Flutter的客户端团队,规模差不多的项目,我们的人手是他们的一半。我们交付的稳定性、项目周期可控性、bug率等指标都远好于他们。

应该说TDD充分证明了在这种长期迭代的项目中的可靠性和项目收益。


那么回到文章最开始的问题,在短期项目中是否值得使用TDD呢?

我的观点是只要你的项目不是那种写完代码不需要改bug就交付的类型,那TDD一定能带来正收益。

这几年我们也做了几个临时性的小App,都是不需要后续长期维护的那种。

我们全部沿用TDD流程,结果也如预料,项目的测试周期、交付质量和我们的主项目基本一致,远高于以前的原生项目。

所以真的不要再觉得写测试代码是花了额外的时间,这些时间本来就是用于进行设计的。

你只不过是换了一种概要设计和详细设计的方式。

而得到的收益就是你的项目从架构到代码细节的质量再到后期修改和维护的能力都得到了不可思议的提升。


好了,本文主要是结合我过往的TDD实战的经历,希望能从理论上说明TDD在不同类型的项目中能给我们带来哪些收益。

下一篇文章,我会结合成都客户的具体情况和我们自己在Flutter上实践TDD的过程来讲讲基于Flutter的TDD具体流程和技术细节。


如果看到这里的同学有学习Flutter或者TDD的兴趣,欢迎联系老刘,我们互相学习。

点击免费领老刘整理的《Flutter开发手册》,覆盖90%应用开发场景。

可以作为Flutter学习的知识地图。

覆盖90%开发场景的《Flutter开发手册》


作者:程序员老刘
来源:juejin.cn/post/7441479625971318835
收起阅读 »

📢 程序员注意!这些代码可能会让你"吃牢饭"!

关注我的公众号:【编程朝花夕拾】,可获取首发内容。 01 引言 不知道你有没有听过面向监狱编程,可能你好好的码着代码,就就被帽子叔叔带走了。 "我只是个写代码的,关我什么事?" 这是深圳某P2P平台架构师在法庭上崩溃大喊,但代码提交记录中的"反爬优化注释"...
继续阅读 »

关注我的公众号:【编程朝花夕拾】,可获取首发内容。




01 引言


不知道你有没有听过面向监狱编程,可能你好好的码着代码,就就被帽子叔叔带走了。


"我只是个写代码的,关我什么事?" 这是深圳某P2P平台架构师在法庭上崩溃大喊,但代码提交记录中的"反爬优化注释"成了铁证——他因非法吸收公众存款罪获刑5年。这不是电影,而是2023年真实判决!


程序员早已不是免责职业,你的键盘可能正在敲响监狱的大门!


02 血泪案例


⚠️ 这些代码真的会"坐牢"!


2.1 爬虫爬进铁窗


爬虫其实是最容易爬进铁窗的代码。当时可能只是为了解决一个业务痛点,一旦被非法使用,就可能触犯法律的红线。开发者无意,使用者有心,莫名其名的就背了锅。


案例:


浙江某程序员用分布式爬虫狂扫10亿条个人信息,庭审时辩解:"技术无罪!"。


法官怒怼:"每秒突破5次反爬验证,这叫'技术中立'?" —— 6人团队全员获刑!


所以,我们在日常工作中开发爬虫就应该得到启示:



  • ✅数据是否涉个人隐私?

  • ✅是否突破网站防护?

  • ✅对方是否知情同意?


实在拿不准,公司一般都会有法务,可以咨询。


2.2 权限变"凶器"


我们在开发过程中为处理决异常数据的问题,可能会在代码里面留后门。正常的业务功能本身没有问题,但是涉及支付、数据安全等行为,就要注意了。被他人恶意使用,不仅会造成财产损失,可能会还会勉励牢狱之灾。


案例:


杭州前程序员偷偷植入"定时转账代码",21万公款秒变私人财产。检察机关以马某涉嫌盗窃罪、妨害公务罪向法院提起公诉,经法院审理作出一审判决,马某被判处有期徒刑四年二个月,并处罚金。


该起事件也为程序员们敲响了警钟。玩归玩,闹归闹,法律红线不可碰。


🛑 高位操作清单:



  • ❌ 私留系统后门

  • ❌ 超权限访问数据

  • ❌ 删除/篡改数据或日志


2.3 "技术黑产"陷阱


程序员除了工作之外,很多人可能还会通过接私活,如猪八戒网等。以此增加自己的收入。没有公司的严格审核,很多程序员就会掉如技术黑产 的陷阱。


案例:


湖北大学生接私活开发"诈骗APP",庭审播放需求录音:"要能后台改赌局结果"。可能当时你只想着:"我只负责技术实现" 最后却成诈骗案从犯!


尤其一些关于支付的似乎要尤为谨慎,特别是支付成功后,限制体现的时间,很有可能就会用于非法洗钱的黑坑里。


🔥 接私活避坑指南



  • 👉 要求签署书面合同

  • 👉 录音确认需求合法性

  • 👉 转账账户必须对公


03 为什么程序员总成背锅侠


其实大多数程序员都是很单纯的,尤其那些喜欢挑战的程序员。他可能只为表现自己的实力,仅仅只是按照需求开发了功能,但是被恶意利用,最终成为背锅侠


程序员以为法官认定
突破反爬是技术挑战非法侵入计算机系统
按需求开发无过错明知违法仍提供帮助
删除代码就没事电子证据完整链锁定"

血泪真相:你的Git提交记录、代码注释、甚至TODO列表都可能成为呈堂证供!


04 IT人保命三件套


4.1 代码防坐牢套餐


敏感功能增加法律注释。开发的功能以及项目的沟通都要留档尤其需求的变更。因为接到需求的时候可能没有问题,改着改着就出问题了。


拒绝口头需求,落实文档记录,需求、会议、项目事件以邮件的方式存档。


4.2 权限管理生死线


权限管理是保护数据安全的重要措施,但是可能为了调试方便,预留逃逸后门。被人利用轻则数据信息泄露、重则踩缝纫机。


三方对接中,加强公钥、私钥的管理,防止恶意推送或者拉取数据。敏感信息是否脱敏,都是开发中需要考虑的要点。


如果有必要,增加埋点记录,日志记录。收集用户的操作行为。


4.3 法律意识


每个IT公司都会面临网络安全的检查,可以多了解一些相关的法律发条。至少了解那些数据可能会属于需要保护的数据,引起重视。


如果公司允许,可以多参加一些《数据安全法》《网络安全》等的培训。


05 技术向善


代码改变世界,这个不是一句虚话。运用好技术,代码也可以是光。


阿里巴巴的支付宝硬是借助技术,将全国带入数字支付的时代;疫情期间的随申码、一码通等,为战胜疫情作出了巨大贡献;大模型的火爆推送了智能时代的到来等等。


真正的大神不仅代码能跑通,人生更不能"跑偏"!


你在工作中遇到过哪些"法律边缘"的需求?评论区说出你的故事。


作者:SimonKing
来源:juejin.cn/post/7506417928788836362
收起阅读 »

写了7年代码,我有点焦虑了!

很多人都知道程序员是吃青春饭,但是身为程序员的我们却很难感受到,直到某一天跳槽,突然看到坐在对面的面试官比自己还年轻,问的技术自己都是最新的,是不是觉得不服老都不行了 我是92年出生的,13年下半年入职第一份工作, 至今写代码经验已近7年。 职场经历也是有过多...
继续阅读 »

很多人都知道程序员是吃青春饭,但是身为程序员的我们却很难感受到,直到某一天跳槽,突然看到坐在对面的面试官比自己还年轻,问的技术自己都是最新的,是不是觉得不服老都不行了


我是92年出生的,13年下半年入职第一份工作, 至今写代码经验已近7年。


职场经历也是有过多种角色,初级程序员、中级程序员、高级程序员、项目经理、小组长、后端负责人等等。


除了短暂的做过政府项目、企业内部建站项目等,大部分还是混迹在互联网项目,项目经验也算是比较丰富。做过很多失败的产品,也参与过日并发近千万的项目,但是还是抵不住我的焦虑。


为何焦虑?


家庭开支和各类贷款


因为结婚生娃了,家庭开支压力也来了,如果不是靠着副业收入的补贴其实是很难存下来钱的。


深圳的生活压力其实挺大,稍微算了下每个月的支出从去年开始已经差不多稳定超2w了。


生活成本:房租3700+车贷4300+老家买的房贷2300+ 两个大人一个小孩的支出7000+


车贷目前还有3个月就还完了,这点倒是可以松一口气。


年龄和环境


再有2年就迈入30岁这个槛了,都说男人30而立,但是对于30岁的程序员来说,能保留一头浓密的头发已是万幸,我已经有这个趋势了,目前还在抢救中,晒个图吧


image-20200812163133017


当然,头发只是顺带的劣势,主要是如果30岁还没走上管理岗或者核心岗,那以后跳槽是相当悲剧的,写代码的如果跨行,多年的项目和业务经验都带不过去,在企业择人的时候,为什么不选个25岁的呢?


再说环境,如果我目前待的公司是世界五百强等牛逼的企业,肯定不会说焦虑这类的东西了,因为往往是那些公司,年龄和经验反而不是事业的阻碍,至少在企业内部不出问题的情况下还能稳定待很久,这个东西往往很现实的,很多工作多年的程序员跳槽的时候,除了考虑到薪资和待遇,对公司的稳定性还是有很大考量的。


很多人包括程序员都觉得,以后大不了年纪大了身体扛不住了转管理,但管理岗是这么容易说转就转的么?没有经历过带团队和带项目的你,给个团队你带岂不是带的一团糟,所以在这里建议程序员在工作中尽量体验多种角色,比如说小组长、项目负责人、项目经理或者团队负责人等等,不仅能在沟通上锻炼弥补程序员的不足,做出一定成绩了还能在工资和待遇上体现出来,这点我是深有体会。


对转业后的迷茫


本来想说退休的,有点歧义,这里叫转业吧。


转业是不可避免的事情,至于啥时候转业,啥时候考虑转业,还是根据个人所处环境决定的。


有的人在大公司,公司业绩蒸蒸日上,手握大把股权,自然不会考虑到这上面


但这是更多普通程序员的必走之路


所以很多有想法的程序员会对转业前有一个前期规划,大体上就是:工资+副业+理财


作为我来说,理财这方便目前还是小白,其他两个马马虎虎吧。


所以还得继续加油


年轻的程序员和上了年纪的程序员


认识一些之前共事的程序员朋友,在聊天的过程中发现,年轻的程序员不太喜欢安于现状,当环境或者薪资达不到自己期望的时候,就会选择跳槽,而且大概率能找到待遇比之前公司好的,上了年纪的程序员喜欢求稳,因为一份工作已经来之不易,养家糊口不容易,没那么喜欢折腾了。


同学小A


小A是我的大学同学,在近期有过一次跳槽,虽然其他待遇比之前公司差了一点,但是工资却是足足涨了5k,从25k涨到了30K.



虽然待遇提升了,但是还是避免不了程序员从一个坑跳另一个坑的魔咒,入职第一天就开始吐槽项目代码~


image-20200812171620405


对此我只能深表同情~


同事小B


小B是之前的同事,算算时间竟然也认识5年了,5年前就是前端leader,目前已经35岁了,我们有共同的群聊,一直保持密切沟通,这点我觉得在维护同事关系上还是做得不错的。


小B目前也是一家公司的leader,这两年又生了二胎,加上前几年在惠州拿了一套房,经济压力还是挺大的,当我们聊到跳槽这个话题的时候,想不到也是怂恿不动,一心求稳。不过小B保养有道,一个35岁的大龄程序员竟然看起来和毕业生差不多,想必还能写5年代码。



写到最后


焦虑这个话题,感觉不适合写长篇大论,只能草草收尾了,以下几点是写给大龄程序员以及自己的建议:



  • 做好长期合理理财。你不理财,财不理你,以前看到相关理财软文,其实是比较反感的,但是当身边一些朋友通过合理理财并获得比较理想回报的时候,我就在拍脑袋,觉悟跟不上啊。

  • 有上位机会的尽量不要错过。认识很多程序员当上面让他顶上去的时候都喜欢退缩,如果你的程序员生涯只仅限于写增删改查,那么多年以后真的只能做增删改查被淘汰了。当领导是会背锅,是会压力大,但是你收获的会更多。

  • 调理好身体。这点我就做的不好,已经有脂肪肝了,每年体检都会有点大大小小的毛病,身体就是革命的本钱,年轻的时候赚的再多,不搞好身体都会交给医院


看到这了,但凡有点共鸣,点赞转发走一波?


作者:GitHub摸轮子啊
来源:juejin.cn/post/6860043925357821966
收起阅读 »

项目经理训练两年半,我决定回归做程序员了

23年因一次机缘巧合,我从程序员转岗为项目经理。这之前,我已在程序员岗位摸爬滚打了近5年,当时的自己似乎已经看到了技术生涯的天花板,尤其是前端和 Web 开发领域,那把35岁“达摩克利斯之剑”仿佛始终悬在头顶。于是,我头也不回地扎进了项目管理岗位,远离了熟悉的...
继续阅读 »

23年因一次机缘巧合,我从程序员转岗为项目经理。这之前,我已在程序员岗位摸爬滚打了近5年,当时的自己似乎已经看到了技术生涯的天花板,尤其是前端和 Web 开发领域,那把35岁“达摩克利斯之剑”仿佛始终悬在头顶。于是,我头也不回地扎进了项目管理岗位,远离了熟悉的编辑器、代码与熟悉的团队。


回过头来看,疫情以来,互联网行业确实进入了大规模收缩期,程序员裁员新闻频繁爆出,我一度还庆幸自己的选择:“看来转岗是对的?”


可两年半后,在项目管理岗位上逐渐摸索成长,我却越来越清晰地看到“真实的自己”——可能我对工作的真正热情依然在于编程、在于技术。


一、认“真”与乌托邦


如果二十岁出头的年纪,还可以坦然地追求理想、抱着点乌托邦的情怀,倒也无可厚非。但三十岁左右,面对现实生活压力,似乎早该学会“世俗圆滑”,甚至当一个愤青、表达不满,都会被人视作“不知所谓”、“单纯幼稚”。


然而,每次试图“再忍忍”,内心总会不平静,耳边总回响起中学时代背诵的诗句:“竹杖芒鞋轻胜马”、“三十功名尘与土,八千里路云和月”、“穷且益坚,不坠青云之志”……想想,也不过就是从头再来?


以前我一直认为“认真”是个褒义词,但现在别人一提起“认真”,心里就会一阵不适:



  • 认真=负责? 那是做好牛马的前提,是被消耗的好耗材。

  • 认真=老实? 脾气好、有教养,最适合被人拿枪使。

  • 认真 vs 苟着? 难道想要站着把钱挣了不成?


在项目管理工作里,我再也感受不到编程带给我的那种纯粹、干净与安静。很多时候,大环境之下个体无法改变什么,哪怕你再坚持原则,也不强过如“铁笔换木枪”,一瞬即逝。


所以,我最终还是决定回归代码,至少在技术世界里,纯粹依旧值得追求。


二、开源精神与自由


做项目经理时,我学习了 PMP,了解了职能型和矩阵型组织结构。现实告诉我,矩阵型的项目管理在落地执行时往往演变成职能部门之间的推诿扯皮,“要发展就要搞关系”似乎已成为铁律。


与之相比,代码世界却截然不同。编程圈的开源精神是开放的、普世对等且包容的,它不拘泥于等级资历,这才是它真正迷人的地方。这种去中心化的世界,能够带给我们真正的自由感。


正因如此,我更加明确地感受到,自己真正热爱的、追求的依旧是编程,是技术带来的自由与纯粹。


未来,不论环境如何变化,我都会坚定地回归代码。


立此帖为证。


作者:掘金安东尼
来源:juejin.cn/post/7507908812599296035
收起阅读 »

短信为何没落?

短信,从曾经的日常对话,变成了今天只在收验证码、收通知时才偶尔想起的工具。我们不再用它聊天,但它却以另一种方式,继续默默留在了每一部手机里——像一条永不熄灭的应急通道,安静又顽强。 为什么传统短信衰落了? 我想,原因显而易见: 体验落后:纯文本,沉闷乏味,与...
继续阅读 »

短信,从曾经的日常对话,变成了今天只在收验证码、收通知时才偶尔想起的工具。我们不再用它聊天,但它却以另一种方式,继续默默留在了每一部手机里——像一条永不熄灭的应急通道,安静又顽强。


为什么传统短信衰落了?


我想,原因显而易见:



  • 体验落后:纯文本,沉闷乏味,与今天充满表情包、短视频的社交体验格格不入。

  • 安全问题:垃圾信息与钓鱼链接充斥,带来隐私泄露和金融诈骗风险。

  • 替代者崛起:OTT应用(如微信等即时通讯)越过运营商,构建了更强大且丰富的通讯体验。



一句话总结:自第一代iPhone发布以来,短信从未进化过。


但近两年,5G消息的概念强势崛起:试图“复活”短信。


它被认为是短信的升级版,是一种长得更好看的短信,支持文本、图片、音频、视频、定位、支付、卡片应用等丰富媒介内容,如图。它试图成为新的“杀手级应用”,补齐传统短信缺失的智能与体验。



但问题来了 —— 对用户来说,这些体验在APP应用里早已稀松平常,“了无新意”。。。5G消息远远谈不上颠覆,只是跟上了过去的潮流。


思考


这里想问大家一句:短信最大的优势是什么?


—— 我认为可能是有一点:那就是 “强推送“ 。即只要拿到了手机号,不管你愿意不愿意,就能给你发短信!


—— 这个可以是正向积极的、比如,如果在地震台风来临时,谁也不想错过“被强推送”一条预警消息。或者:你订阅了关注金价走势的服务,每天早上9点,直接推送一条金价信息,也不会让人太反感尔尔。


—— 也可以是负面消极的,比如消息轰炸、低劣推销、骚扰信息的等。



本瓜认为:真正的变化不应该是“形式”,应该发生在基础设施层



现在的消息生态,并不是单一平台控制的,而是:运营商、手机厂商、MaaP平台、AI服务商、HUB厂商、SDK厂商、企业用户等多方共建。


多方参与虽然打破了垄断,但也带来了潜在的协调低效与体验分裂问题。



移动互联网的成功经验告诉我们:轻应用,才是黏住用户、构建生态的核心。


1、对用户而言:免安装、免更新、即用即走、无缝切换。—— 是好的!


2、对开发者而言:开发简单、成本低、快速迭代。—— 也是好的!


在App平台上,代表性的轻应用是小程序。而在5G消息体系里,对应的是Chatbot(聊天机器人) 。—— 就有点像把如今火爆的智能体加入到短信里。


虽然聊天机器人前端看似简单,但背后隐藏着巨大的开发挑战:不仅是UI,而是要设计对话剧本、逻辑分支;还有自然语言输入不确定,需要NLP、NLU技术精准理解;需要训练、调优,否则容易出错让用户失望等等。


对企业来说,想开发一个成熟Chatbot的难度和投入,远超表面。所以,这也是为什么现在你还没有开始在短信界面呼起各类机器人/应用。


未来企业很可能同时包含:



  • App:重应用,沉淀核心用户。

  • 小程序:轻应用,覆盖广泛场景。

  • Chatbot:对话应用,增强即时服务与主动触达能力:智能客服、营销互动



问题又来了: 要支撑这样分散、灵活、快速演化的格局,需要怎样的基础设施?



可能需要一套完善的 沙箱计划:即允许应用以轻量方式接入、运行、管理,同时保障数据隔离、安全合规。


作者:掘金安东尼
来源:juejin.cn/post/7503462035272073266
收起阅读 »

纯血鸿蒙 璀璨星河

华为最近可谓是加班加点,前段时间华为给出了鸿蒙系统的计划表,让大家都摩拳擦掌,想看看华为到底有几把刷子,这次的621HDC大会,就是华为给全世界的第一个交待。 最近在网上经常流传着这样一张图:大体意思就是:根据Counterpoint Research报告显示...
继续阅读 »

华为最近可谓是加班加点,前段时间华为给出了鸿蒙系统的计划表,让大家都摩拳擦掌,想看看华为到底有几把刷子,这次的621HDC大会,就是华为给全世界的第一个交待。


最近在网上经常流传着这样一张图:
image.png
大体意思就是:根据Counterpoint Research报告显示,今年一季度,鸿蒙在中国市场份额为17%,而苹果的iOS为16%。这意味着,鸿蒙在中国市场首次超越iOS,成为中国市场第二大智能手机操作系统。


这张图呢,可以说没问题,但也有问题,具体是什么问题呢,我们后面再说。


首先,我们要先来了解下,什么是「鸿蒙」。


对于一般用户来说,当前对鸿蒙可能没有什么概念,因为现在的华为手机上,跑的就是鸿蒙系统,但此鸿蒙,非彼之鸿蒙,当前市面上的所有在售华为设备,运行的都是「基于Android系统的鸿蒙系统」,也就是说,图中的鸿蒙系统,实际上就是华为的基于Android系统修改的鸿蒙系统。所以这图中的操作系统对比,实际上就是在偷换概念,这其实就是华为设备的占比。


那么为什么现在还在炒作什么国产新系统呢?这不妥妥的套壳吗?确实,现在的鸿蒙还是在套壳,但是今年以后的鸿蒙,可能就不是了。


这就是我们今天的主角——纯血鸿蒙。



鸿蒙采取的策略,实际上和当初的Android类似,先以Android系统为底,建立华为生态和用户群,再通过建立全新的操作系统,来和Android割裂,完整的建立自己的生态。



所以,现在的纯血鸿蒙,实际上就是「HarmonyOS NEXT」系统,这个系统,与现有Android系统完全不兼容,属于一个完整的自建操作系统,再也不是套壳了。


根据我多年的鸿蒙开发经验(特别是这3个月的),纯血鸿蒙确实博采众家之长,有点东西。


其实,做一个操作系统不难,难的是做一个生态,华为的投入可谓空前巨大,从开发工具链到社区,从硬件设备到软件开发,整体的投入都是前所未有的,这也体现了高层,对国产操作系统的信心和决心。


虽然现在纯血鸿蒙还处于初级阶段,但带着发展的眼光来看,确实是极具潜力的,根据我的经验来看:



  • 渲染系统吸取了各大平台的特点,这么多年以来,各大渲染体系该踩得坑都踩完了,现在华为可谓是一将功成

  • 响应式开发体系也做了很大改进,但是感觉设计有些过于复杂,颗粒度太细,上手成本较高,同时由于现在开发API还不稳定,变动较多

  • 开发生态逐渐完善,和苹果类似,华为又做硬件又做软件,所以它自己可以很方便的整合自家资源,它绝不仅仅是一个操作系统,更是一个生态平台,可以融合自己的AI大模型、多端平台共享、多端接续等等生态功能

  • 开发语言包容性强,js、c、TS、ArkTS、dart、kotlin等等不同的语言生态,都有社区对鸿蒙的支持,这些社区中,有很多都是华为的开发人员,在帮助社区共建,所以,各个不同的平台系统,都可以很快的用自己的技术栈,接入鸿蒙系统

  • API很丰富,但也是一把双刃剑,华为在对接很多开发者,为他们提供了很多便利的API,但是也由于快速迭代,API的设计可能缺少深思熟虑,有些API会有些冗余、随意

  • 整体架构来说,有很多Android的影子,也借鉴了很多Flutter的渲染机制,开发者在开发的时候,总能不在意的会心一笑


621之后,纯血鸿蒙中会有大量的APP上线,基本已经涵盖了日常使用功能,作为开发者,我们来看看这些常用的APP,看下它们都是用的哪些技术栈进行开发的。


Screenshot_20240621102104400.jpegScreenshot_20240621102132997.jpeg
Screenshot_20240621102240537.jpeg
Screenshot_20240621102352584.jpegScreenshot_20240621102402095.jpeg
Screenshot_20240621102422429.jpeg
Screenshot_20240621102437862.jpegScreenshot_20240621102447012.jpeg
Screenshot_20240621102500363.jpegScreenshot_20240621102510978.jpeg
Screenshot_20240621102524579.jpegScreenshot_20240621102535512.jpegScreenshot_20240621102545314.jpeg
Screenshot_20240621102609562.jpegScreenshot_20240621102622761.jpeg
Screenshot_20240621102641945.jpegScreenshot_20240621102656395.jpeg
Screenshot_20240621102713911.jpeg
Screenshot_20240621102735295.jpeg
Screenshot_20240621102750312.jpegScreenshot_20240621102804860.jpeg

这里我找了市场中已经上线的一些典型APP,利用纯血鸿蒙的开发者选项中的布局边界,来大致揣测下它们的技术方案。


从业务形态上来看,这些APP大致分为几种:



  • 信息流:这类的APP,其实就是纯粹堆UI,大部分都利用ArkTS进行开发,只要熟悉ArkTS语法,开发难度不大,但需要堆人力,因为很多组件都需要从零开始开发。

  • 自渲染:这类的APP,以视频、小说类为主,这些APP相对来说比较复杂,但是视频类,相对来说会好一些,比较大部分复杂的音视频处理,都在C层时处理了,所以上层业务,提供鸿蒙的适配方案就行了,而小说类的,文字渲染相关的API和刷新方案,都需要重新按照鸿蒙的架构思路来重新实现,所以开发难度会大一些。

  • 跨平台:通常基于Flutter的方案来实现,这里的典型就行闲鱼,现有业务可以直接移植过来,只需要在Channel层适配即可,如果公司当前有Flutter架构,那这是适配鸿蒙的最快方案。


总的来说,当前纯血鸿蒙的设备已经支持高刷,各大应用的完成度也很高,同时,由于时间紧任务重,很多营收类需求都没做,比如广告,所以这个版本应该是非常「纯净」的版本了,整体质量和体验都非常好。


当然,不得不说,现在的纯血鸿蒙依然是初级阶段,现在不管是开发上还是系统上,都还有很多问题,不过,正如那句话说的——「没有人能够熄灭漫天星光,每一位开发者,都是华为要汇聚的星星之火」。


image.png


欢迎大家关注我的公众号——【群英传】,专注于「Android」「Flutter」「Kotlin」
我的语雀知识库——http://www.yuque.com/xuyisheng


作者:xuyisheng
来源:juejin.cn/post/7382892371224494120
收起阅读 »

鸿蒙 PC 发布之后,想在技术上聊聊它的未来可能

最近鸿蒙 PC 刚发布完,但是发布会没公布太多技术细节,基本上一些细节都是通过自媒体渠道获取,首先可以确定的是,鸿蒙 PC 本身肯定是无法「直接」运行 win 原本的应用,但是可以支持手机上「原生鸿蒙」的应用,细节上无非就是 UI 兼容下大屏模式的支持,比如下...
继续阅读 »

最近鸿蒙 PC 刚发布完,但是发布会没公布太多技术细节,基本上一些细节都是通过自媒体渠道获取,首先可以确定的是,鸿蒙 PC 本身肯定是无法「直接」运行 win 原本的应用,但是可以支持手机上「原生鸿蒙」的应用,细节上无非就是 UI 兼容下大屏模式的支持,比如下图是来自 差评XPIN 的鸿蒙 PC 截图:





那么问题来了,HarmonyOS 「卓易通 」 作为生态过渡的丰富支持,甚至在应用商店都可以无缝衔接,那么鸿蒙 PC 是否也可以有类似的场景?



因为目前得到的消息是,鸿蒙 PC 不支持侧载 ,这个结论我也不保熟,只是在这个大条件下讨论,那么 鸿蒙 PC 是不是也可以有个 「W易通」?技术上是否可以支持?



当然,你要说鸿蒙 PC 和鸿蒙手机,本质它们是同源的,App 之间互通理论上没毛病,从这个角度看,好像又支持侧载?


1a187a9eafc3edd514f8e310f5ec8d3b.png


那「W易通」?技术上是否可以支持?答案上还真可以,从某些媒体上说的,通过定制 Wine 来兼容已有的 win 软件,这个或许是一条可行的路,但是其实我也并没有找到官方下图的说法和出处,但是不妨碍我们讨论可行性。



Wine 这个名字本身就揭示了它核心特性:“Wine Is Not an Emulator”(Wine 不是模拟器),它其实已经被应用很久了,例如:



  • Steam Deck 和 Proton,就是那个 Steam 的掌机,它用的就是为极致游戏定制的 Wine ,Proton 是一个为 Windows 游戏能在 Linux 上流畅运行而深度定制和优化的发行套件

  • CrossOver 和 Whiskey,在 macOS 上运行 win 游戏,也是 Wine 的定制


所以 Wine 确实是一个可行的途径,Wine 在实际场景里主要是充当一个兼容层,实时地将 Windows 应用的 API 调用转换为宿主操作系统(如 Linux 或 macOS)能够理解的等效 POSIX 调用 。


当然,这种设计也意味着 Wine 的兼容性直接取决于其对 Windows API 的重实现程度,所以 Wine 的核心就是重塑 Windows API ,在某种程度上镜像了 Windows 的结构,例如:



  • wineserver:在 Windows 中主要是由内核提供核心服务,在 Wine 中会由 wineserver 在用户空间实现 ,它的职责包括实现基本的 Windows 功能,如进程和线程管理、对象管理、进程间通信(IPC)、同步原语、将 Unix 信号转换为 Windows 异常,处理窗口管理和输入事件等

  • 核心 DLL 的重实现:Wine 提供了大量核心 Windows DLL 版本,例如 NTDLL.DLL(Windows NT 内核功能的核心接口)、KERNEL32.DLL(基础操作系统功能,如内存管理、文件 I/O)、GDI32.DLL(图形设备接口,负责 2D 绘图)、USER32.DLL(用户界面元素、窗口管理、消息传递)等 ,这些 Wine 实现的 DLL 通常以 Unix 共享对象(.so 文件)的形式存在,它们可以直接调用宿主操作系统的函数


另外 还有 WineD3D ,将 Direct3D 和 DirectDraw API 调用翻译成 OpenGL 调用的核心组件 ,另外还有 DXVK 这种专注于将 Direct3D API 调用高效地翻译成 Vulkan 调用的支持。



前面的 Steam 的 Proton 也是一个针对游戏优化的 vkd3d 分支,负责将 D3D12 调用翻译为 Vulkan ,而 macOS 上或者还需要比如 MoltenVK 将 Vulkan 转为 Metal ?



当然,翻译 API 的局限性就不用多说了,还有一些依赖底层驱动支持的场景,很难在通用性上做到完美,当时理论上做到部分应用通用的场景应该可以,甚至在游戏领域反而更有优势?


当然,还有另外一条途径就是直接跑虚拟机,或者说虚拟桌面,目前已经有不少人运行成功,比如就有博主用 Os-easy 虚拟机装上了Windows 11 :




事实上 Linux 上运行 Win 虚拟机一直以来就有,用户只需选择镜像文件并完成基础配置,同样也可以在鸿蒙 PC 上使用Windows系统。


安装完成后,用户可以在鸿蒙与 Windows 系统之间便捷切换,类似切换桌面的效果,这样也算是一种场景支持:



当然,虚拟桌面的割裂感会更重,但是在通用软件场景下会相对更好,但是性能也许会更差一下?


另外,目前也挺多觉得鸿蒙 PC 就是一个平板 PC 化的场景,其实这样也算是一个趋势?类似我前段时间一直在聊的 Android PC 化支持,目前 Android 桌面化已经集齐:



  • Linux 终端控制台支持

  • 桌面模式

  • 外部显示器支持

  • 窗口多任务,最小化,多实例支持

  • 尚未明确的 Desktop View

  • 外部显示器排列和切换

  • ·····


例如下方就是 Android 下的外部显示器排列和切换支持:



最后,貌似目前鸿蒙 PC 虽然能进终端,但是不开放 sudo 权限,apt 也没有?这部分能力不知道后续是否会开放,从 PC 角度看这部分能力还是有必要的:



比如小米这个 winplay 是不是也是 wine 的定制魔改?我个人感觉,鸿蒙 pc 上游戏通过 wine 体系支持可能会比虚拟桌面更好


a723d34463601e3adb5da2daa42c024.png


那么,对于鸿蒙 PC 场景,你有什么技术方向想聊的?


作者:恋猫de小郭
来源:juejin.cn/post/7503450078159470646
收起阅读 »

这只是一罐过期了七年的红牛……

可能是临近假期,昨天眼睛乱晃时,偶然间在我的办公桌角落上发现一罐红牛。当我看到它的第一眼,就想起了很多事情。我知道它已经过期很久了,我还能模糊地想起当年隔壁部门领导送给我们的那个场景,也还能想起早已离职的同事们相处的日常…… 这罐红牛啊,过期很久咯 但当我拿过...
继续阅读 »

可能是临近假期,昨天眼睛乱晃时,偶然间在我的办公桌角落上发现一罐红牛。当我看到它的第一眼,就想起了很多事情。我知道它已经过期很久了,我还能模糊地想起当年隔壁部门领导送给我们的那个场景,也还能想起早已离职的同事们相处的日常……


这罐红牛啊,过期很久咯


但当我拿过来仔细一看的时候,才有点感慨,我知道它过期很久了,但没想到已经过期快 7 年了。也就是说,我来这个公司已经快 9 年了。作为一个2016年软件工程985本科毕业的年轻人,守在一个工厂拿着远远远低于行业平均水平的死工资,居然已经快 9 年了。我甚至敏感到与这罐红牛“感同身受”。



  • 年轻时,无穷的精力和旺盛的斗志,对未来也是无限美好的憧憬,根本不需要红牛来提神。

  • 过几年,经历越来越多的挫败和不如意,发现事情越来越不受自己控制,一罐红牛能起什么用。

  • 后来啊,感觉自己前途和命运(身体与灵魂)都不属于自己、无法掌握,一罐红牛又算什么东西。

  • 现在啊,孙连城是对的,就应该多看星星,“胸怀宇宙”,相比之下一切都是小事,红牛本来就只是用来提神的。


可惜的是,这罐红牛过期快七年了,它还能再提神吗?就和薛定谔的猫一样,不在困倦的时候去喝掉这罐红牛,我根本不会知道它还能不能提神。但是呢,我不敢喝。



  • 如果只是想要提神,再买一罐没过期的就好了。但是这罐过期的红牛,再也回不到没过期了。

    • 就像我在这工厂呆了九年,也三十多了,再也回不到二十多岁的时候了。但永远都有充满无限精力、天真稚嫩的二十多岁的小伙子。



  • 或许只是我还把它遗忘在办公桌的角落,所以它还存在;换成别人,可能早就喝掉了;或者也放过期,但是也早扔掉了;罐子可能回收利用,继续发光发热,也可能埋在哪个角落,慢慢副食氧化……

    • 会不会也偶尔觉得自己“空有一身济世救人的才华和抱负却无处施展”?像个废物不被重视。



  • 既然已经放在角落那么多年了,我也打算继续放在那里。那个不起眼的角落,只会占那么小小的一点地方,我不会在意,别人更不会在意。

    • 我不知道我还能在这里待多久,到时候我会带它走吗?可能不会了吧,毕竟它也没什么用了。象征意义大于实际,就像我也不主动联系那些没什么交集、感情不深的老同学、前同事。




过期红牛.jpg


自怨自艾啊,都知道是没用的


我觉得“最近行情不太好”这个话术,我很久没有去听了,也可能是刻意没有去关注。原因倒也简单,之前还想着说不定好好准备换个“钱多事少离家近”的工作。后来就是“我先保住这份工”,什么事情到时候再说吧。现在我多“乐观”,不管什么事,到时候再说吧。


就像也偶尔看到什么统计数据,结婚登记人数越来越少,离婚登记人数越来越多,“或许大家都还在纳闷不知道为什么呢。”


这很难的,就像我表弟刚工作 3 年,就开始在担心“35 岁危机”。未雨绸缪、眼光长远一点问题没有, 但是呢:



  • 要命的是光担心肯定是一点用没有,因为你只是担心、忧虑这个情况,并没有想到应对策略,那真正面临的时候,还是无所适从。

  • 更要命的是,不管你担心与否、忧虑与否,这个“危机”一定存在。

  • 更更要命的是,你知道,但是解决不了。

  • 就像我表妹指着我对表弟所说:“你慌什么,到时候先死的是他。”这一点毛病没有,我是没几年就 35 了,而且我到现在也没有具体应对策略。但更更更要命的是 ,我死了并不能缓解我表弟的担忧,看着我毫无办法或许更加重他的忧虑。


那我还会担心吗?偶尔吧。毕竟就像以前所说的,我与自己和解了,认清了现实,接受了平凡而普通的自己。可惜的是自己看清楚了,好像并没有很大的用处,因为似乎现代人很难作为一个独立的个体而生存。简单说起来就是"帅哥/美女与金钱"(爱情和事业)。



  • 我一个月倒还想拿个几百万呢,但是老板不给我啊?什么,我为什么不去当老板?

  • 我也想相敬如宾、举案齐眉、儿孙满堂、本枝百世,可还是单身。什么,我为什么不去找对象?


八旬老头老太太经常打电话问我:“你要好久才找对象哦”、“你结婚了我们才放得下心哦”、“我们天天焦得瞌睡都睡不着啊”……


我是很难去回应这种期盼了,甚至有时候不知道他们是真关心我生活,还是因为“你大孙 30 多了还没结婚啊,好搞笑哦”太没面子。毕竟时代不一样了,我可能不接受但可以去理解他们的老思想,但他们却不理解也无法接受我们新时代,就好像他们真的觉得想找对象马上就找的到,想换工作马上就换得到,想长生不老喝口水就可以了一样。


说多了大家都不爱听,所以我一般只会阿巴阿巴。


与自己和解?我只是随口一说


偶尔我会觉得,大部分普通人的人生经历都是类似的,只有那些真正“我命由我不由天”的少数人才的成功,比较难以复制。这也是我认为“经验之谈”大部分时候都是有效的。


可惜的是,经验之谈往往只有个结果,每个人的真正经历的细节不太一样,每个人的理解能力不太一样,时代背景也不一样,导致处理过程可能就不通用了。我说“与自己和解”之后,我的人生畅快了很多,但有些陌生的朋友来和我交流的时候,我却爱莫能助,也只能提个结论。



  • 深情是不是舔狗?没钱是不是铁废物?

  • “事前同意不代表事后同意”到底是什么原理?

  • “我只是希望你上进”到底是什么意思?

  • “我真的不想耽误你”到底是不是一片好心?

  • “我真的希望你有更好的未来”是不是真心的祝愿?

  • ……


“乱花渐欲迷人眼”,很多时候我看不明白,我就不爱看,我就做个“逃避者”,你觉得可耻关我什么事呢。这个时代到底需不需要阿 Q 精神?“只有对社会没用的废物才会想着放假,我们这些栋梁之才一心做建设,根本不需要放假。”


……


这样的生活多累啊,但是作为人的话,本来就很复杂。就像我曾以为我可以大展宏图发光发热,但是我错了;也以为自己遇到了对的人,然后又错了……


事实上,那罐红牛没有思想,我摆在那里,它就在那里,而且一直在那里。它不会开心、不会难过,也不会发表长篇大论咋咋呼呼。而且在那已经过去的8年,不管它是否过期,它都没有意识,它根本不关心,而且其实我也TM根本就不在乎它,全都是我顾影自怜而已。


或许可以试着当一罐过期的红牛?


就像我记得去年四五月的时候,各个云平台的AI大模型API或大幅度降价或者免费,我就在想能不能借助这些资源做个什么东西出来,还给好几个平台充了钱。一年过去了,但还是不知道能拿来做什么,依旧和最初的想法一样,调用各个平台API进行聊天对话而已,其他富有创造性的想法,完全没有。甚至在年初DeepSeek爆火之后,像我充钱的零一万物、智谱AI啥的,都没有特别大的声音。


或许有能力的人,先有超凡的思想,然后又脱俗的能力,所以才是弄潮儿。一年过去了,我还是没有想到能借助AI浪潮搞点什么,最多是用上了cursor并逐渐接纳了它。


但是,不管我怎么看待AI浪潮,它都会发展。就像5G、Web3、元宇宙……你不管以后对它们的定义是什么,它们都有着自己的发展轨迹,可能有的生命周期长点,有的Y轴高点,有的依旧不被很多人看好……


虽然我不是“宇宙区长”,我的生命还有那么长,“人生在世屈指算,也就三万六千天”。但就算到了35岁,也才三分之一,到目前的法定退休也才二分之一,我才进社会多少年,那后面的那些年就不过了?


或许可以当一罐过期的红牛,就默默地待在角落,世间的美好,人性的险恶,都如过眼云烟,我自岿然不动。


或许我只是想当这一罐过期了 7 年、却还没被我丢掉的红牛,可以长久在无人关注的角落,享受着自己孤独的快乐。




最后,还是分享一下我最新版本调用云平台大模型API的聊天应用,万一正好有朋友需要呢。


桌面主页面预览:


screenshot-home-desktop.png


移动端截图:


screenshot-mobile.jpg


若有兴趣,更具体内容可访问github查看:Sanotsu/SuChat-Lite


以上,感谢垂阅。


作者:小流苏生
来源:juejin.cn/post/7498292516492476450
收起阅读 »

不容易,35岁的我还在小公司苟且偷生

前言 前几天和前同事闲时聚餐,约了两个月的小聚终于达成了,程序员行业聚少离多,所幸大家的发量还坚挺着。 期间不可避免地聊到了自己的公司、行业状况以及对未来的看法,几杯老酒之后,大家畅所欲言,其中一位老哥侃起了他的职业生涯,既坎坷又无奈,饭后想起来挺有代表性的,...
继续阅读 »

前言


前几天和前同事闲时聚餐,约了两个月的小聚终于达成了,程序员行业聚少离多,所幸大家的发量还坚挺着。

期间不可避免地聊到了自己的公司、行业状况以及对未来的看法,几杯老酒之后,大家畅所欲言,其中一位老哥侃起了他的职业生涯,既坎坷又无奈,饭后想起来挺有代表性的,征得他同意故记录在此。

以下是老哥的历程。



cold.jpg


程序员的前半生


我今年35岁,有房有贷有妻女有老父母。


出生在90年代的农村,从小中规中矩,不惹事不喧哗不突出,三好学生没有我,德智体美没有全面发展。学习也算努力,不算小题做题家,因为只考了个本科。


大学学费全靠助学贷款,勤工俭学补贴日用,埋头苦干成绩也只在年级中等偏下水平。有些同学早早就定下了大学的目标,比如考研、比如出国、比如考公,到了大三的时候大家基本都有了自己的目标。而我的目标就是尽早工作,争取早日还完贷款,因此早早就开始准备找工作。

也许是上天眷顾,不知道怎么就被华为看重了(那会华为还没现在的如日中天,彼时是BAT的天下),稀里糊涂的接受了offer,没想到却是改变了后面十年的决定。


2013年,深圳的夏天阳光明媚,热气扑鼻,提着一个简单的箱子进入了坂田基地。

刚开始,工作上的一切都很新鲜,每个人都在忙碌,虽然不知道他们在忙什么,但感觉很高级的样子。同期入职的同事都比较厉害,很快就适应了工作,而自己还是没完全应对工作内容,于是下班之后继续留在公司学习,顺便蹭饭。

就这样,很快就一年过去了,自己也慢慢熟悉了工作节奏,但是加班也越来越多了。对于自己来说,为了过节点,6点是晚饭时间,9点是下班时间,12点正式下班。

平凡的日子没什么值得留恋,过一天、一个月、一年、四年都没什么两样,四年里学习到了不少的知识,也数了很多次深圳凌晨的路灯数。


作为深漂,没有遇到深圳爱情故事,也对高昂的房价绝望,于是决定回到二线城市,成为一名蓉漂。
2017年,还是和四年前一样的行李箱,出现在了老家的省会城市,只是那时的我没有了助学打款,怀里也攒下了一些血汗钱。

那时互联网行业发展还是如火如荼,前端的需求量也很大,也得益于华为公司发展越来越好,自己的华为经历很快就拿到了几个offer,选了一家初创公司,幻想着能有一番成就。


2018年底,眼看着房价越长越高,某链中介不断地灌输再不买明天就是另一个价了,错过这个村就没这个店了,也许是想有个家,也许是想着父母能到省会里一起住,拿出自己做牛马几年的积蓄加上父母一辈子辛苦攒的小十万的养老钱购买了城区里的新房,那会儿的价格已经比前两年涨了一倍多,妥妥的高位站岗,不过想着自己是刚需也不会卖,因此咬咬牙掏出了全部的积蓄怒而背上了三十年的房贷。


房子的事暂时落定了,全身心的投入到工作中,没想到老板只想骗投资人的钱,产品没弄好投资人不愿跟进了,坚持了三年,期间各种断臂求生,最终还是落了个司破人走的境地。


2020年,30岁的我第一次被动失业了,幸运的是也找到了另一半。为了尽可能节省支出,房子装修的事我们都是亲力亲为,最后花了十多万终于将房子装好了,虽然很简单但毕竟是自己在大城市里的第一套房子,那一刻,感觉十年的付出都是值得的。

背着沉重的房贷,期望能找到一份薪资稍微过得去的工作,于是在简历上优势那行写了:“可加班”。依稀记得有些HR对我进行了灵魂拷问:结婚了吗?有小孩了吗?你都30岁了还能加班吗?。我斩钉截铁地说:只要公司有需要,我定会全力以赴!


2022年,我们的孩子出世了,队友辞去了工作全心全意带小孩,而我更加努力了,毕竟有了四脚吞金兽,不得不肝。

虽然工作很努力,但成果一般,不是公司的技术担当,也不会是技术洼地。


2023年的某一天,和之前的364天一样的平淡,在座位上解Bug的我突然感觉到一阵心悸,呼吸不畅,实在不行了呼唤同事叫了120,去医院一套检查下来没发现什么大问题。医生询问是不是工作压力太大,平时加班很多?我说还好,平时也就加班到9点。医生笑了笑说你这种年轻人我见多了,都是压力大的毛病,平时工作不要久坐盯着屏幕多站起来走走。他让我回家多休息,回去后观察了几天还是偶尔会有心悸,再去了另一个医院进行检查,也是没有明确的诊断结果,只是说可能是这个问题,又可能是另一个问题。

过了1个月后,身体上的问题不见好转,我辞去了工作。


2023年末,找了一家小公司,也就是我现在的公司,工资没有涨,仔细算起来还变相下降了。

还是做的业务需求,也没有领导什么人,管好自己就行,直属上级还是个工作几年的小伙。这家公司主要的特点是不加班,技术难度不高,能做多少就是多少,前提是要报风险,领导也不会强迫加班。


就这样到了2024,神奇的是我已经很久没有心悸的感觉了,不知道是不加班还是心态转变的原因。
家里的小朋友也长大了,会说话了。我现在每天下班最温馨的的是她开着门期待我回家的那一刻,她的期盼的眼神就是我回家的动力。


公司在2024年也裁了不少人,领导也找我谈过问问我的想法,我说:我还是能胜任这份工作的。领导说:公司觉得你年级大了一些,工资虽然不是最高,但不太符合行情,你懂的。我说:我懂,可以接受适当的降薪。
就这样,我挺过了2024,然而过了一周领导走了。


2025年,我35周岁了。
现在的我已经彻底接受自己的平庸的事实了。在学生时代,从来都不出色,也不会垫底,就是那类最容易被忽略的人。在工作时代,不是技术大牛,也不是完全的水货,就是普普通通的程序员。


如果说上半生吃到了什么红利,只能说入坑了计算机这行业,技术给我带了收入,有了糊口的基础。没进股市,却被房价狠狠割了一道。


35岁的我,没有彻底躺平摆烂,也没有足够奋发进取。

35岁的我,有着24年的房贷,还好61岁的时候我还在工作,应该还能还房贷。

35岁的我,不吃海鲜不喝酒,尿酸500+。

35岁的我,人体工学椅也挽救不了腰椎间盘突出。

35岁的我,头发依然浓密,只是白发越来越多。

35岁的我,已经不打游戏,只是会看这各种小说聊以慰藉。

35岁的我,两点一线,每天挤着地铁,看众生百态。

35岁的我,早睡早起,放空自己。

35岁的我,暂时还没有领取毕业大礼包,希望今年还能苟过。

35岁的我,希望经济能够好起来,让如我一般平凡的人能够有活下去的勇气。


诸君,下一年再会~祝你平安喜乐,万事顺遂!


太极分两仪,有程序员也有程序媛:30岁的程序媛,升值加薪与我无缘


作者:小鱼人爱编程
来源:juejin.cn/post/7457567782470385705
收起阅读 »

中年程序员,看不惯大公司,去小公司了

我想多些技术传奇,但是为啥总是那么多曲折的世俗故事,这也是别扭极了。 我博客这儿有技术方案,也好多IT行业的狗血故事。盘点了一下,都快成系列短剧了。 再往前,故事更多。而且总是引发着网友的讨论,以及成千上万的关注量。 今天这个故事,讲的是我放弃了大公司,...
继续阅读 »

我想多些技术传奇,但是为啥总是那么多曲折的世俗故事,这也是别扭极了。



我博客这儿有技术方案,也好多IT行业的狗血故事。盘点了一下,都快成系列短剧了。



再往前,故事更多。而且总是引发着网友的讨论,以及成千上万的关注量。



今天这个故事,讲的是我放弃了大公司,去了小公司的故事。


刚辞职离开的公司,是超过500人的企业,不缺钱,很土豪。再之前的公司也都是几百人的公司,最次也是新三板挂牌。而现在,我却入职了一家不到10个人的小公司。


我没疯。


咋说呢?我从大公司干了十多年,又能怎样呢?无非就是混日子,混工资。但是,随着年龄的增长,这种状态还能维持多久呢?我并不想混一天是一天。


很多朋友说,你怎么不继续去大公司?目前的大环境,大公司稳定,抗风险能力强。


但是,我刚辞职的这家就是挺大的公司,其实也并不“稳定”。


我依然是修炼不够,同时不愿躺平之心游丝尚存。



上一份工作,我以为找到了职业生涯的终极归宿,因为它太契合我了。可以说,它需要我,我也需要它。


我做教育信息化10年了,从手机到平板,从客户端到服务端,从硬件到软件,从团队管理到技术方案,再到后来将人工智能融入教育领域。说实话,即便如此,我想找份称心如意的工作依然不容易。因为,一个行业待久了,技能窗口变得既深又窄。比如试卷的电子化和批阅,我就研究了3年,可以说做到了行业领先。


但是,并没有几家公司需要这类冷门的技能。


同样,公司这边也面临同样的问题:找一个经验丰富的业内人,也很难。


我需要一个平台,让我继续研究教育领域的人工智能,我有信心让他成为行业领先。而公司需要一个员工帮它打造专业领域的业务,它也有能力供给我可观的收入。


因此,我俩一拍即合。


这家公司规模大,资金链充足,福利待遇又好。我一度认为,我的职业生涯终于可以稳定下来了,这是个好平台,我立志干到退休。


但是,我错了。


有一天,突然一个同事找到我,说要跟我谈谈。


这个同事不是行政不是HR,也不是我的领导,工作上和我也没有交集。离下班还有1分钟,给我发钉钉让我下班别走。



我当然不惯着他,我问他什么事情。他回复说,等他写完代码。


我说,我还有事,要去车站接人,请尽快。


他叫我去会议室,他告诉我说,我这个岗位是因为有临时需求才招聘的,现在我把活干完了,他也能接手,我就可有可无了。


我问什么意思,要裁我吗?


他说不是,现在只有他能救我,他一句话,我就能留,另一句话,我就得走。


第一次谈话,就这么结束了。算是一个下马威。


第二天,我去找我的直属领导。我问昨天找我谈话的那个白胖子什么角色,他说的话可不可信。


领导说,一半可信,一半不可信。


可信之处在于他是新来高管老郭身边的红人,老郭对他言听计从。不可信之处是他什么都不懂,一动代码就捅娄子,根本接不了我写的AI项目。


后来,我也见识到白胖子的能力,就是特别自信,他知道fastjson是阿里的开源项目,所以它笃定fastapi也必定是阿里开源的。这一点让老郭非常欣赏,因为白胖子总是有肯定的回答。而其技术只会说:可能……也许……大概……不敢保证……


有一次白胖子专门设计陷害一个老实同事,结果得到了老郭的大力支持。这一举动让其他同事既不满又无奈,更多的是害怕。而白胖子则以此示威,更加自信。


后来,白胖子又找我谈话。


他说他不想找我,但是老郭老问,他不得不找我。


他找我的主要目的是跟我谈我该怎么被安排的问题。他说,我现在很尴尬,原因是我的工作很差。主要体现在负责的项目太少,因为目前我手头就一个从0到1自研AI的项目。


我很震惊,手敲一个从0到1的自研AI项目,而且我只报了1个月的工期,保证保质保量地完成,这还不够炸裂吗?!做完了,就是公司的自主知识产品,可以申请专利的那种!这可是一个大项目,类似的项目,我上家公司投入几十万都没干成,后来我用2个月时间做了出来,当时我还受到了集团董事长的接见。


而在这里,我分析需求做定制开发,居然被谈话,理由是活太少?!


他说,你看看别人:小张,这个月干了5件事:修改A项目首页的弹窗文案,将“你好”改为“您好”;给B项目一个500行代码的类加了35条注释;C项目实现了登录功能,代码提交量为1500行……


你说说,人家手里5个项目,而你1个项目,这是5倍的差距。


我说,郭总也这么看吗?白胖子说,当然,郭总多厉害,肯定知道5大于1,小学生都知道。


那怎么办……我问他。他说,我早就说过了,现在只有我能救你。你要有空,我们先吃个饭聊聊,合适的话,我叫上郭总再一起吃个饭……


我说,如果不合适呢?他说,我现在站在个人角度给你聊,要是站在公司角度……


“公司角度怎么样?”


“现在就可以走流程了!你个人能和法人玩得起吗?”


我说,我再想想。


后来,他又找我。



这次,我留了个心眼,打开了手机录音。他还是哪些话,基本就是打压和威胁,只不过更重了一些。


这次我跟他顶嘴了,我说要谈离职也是人事跟我谈,你既不是人事也不是我领导,你没有资格。


最后不欢而散。


回到座位后,我听到从远处传来郭总的声音:怎么这么过分……那怎么能行……简直是不像话……


次日,我已经不打算在这干了。理由是小白胖子并没有什么可怕的,这种人我见多了。但是你一个集团高管居然受制于他,这就奇葩了。


我就把录音发给了HR总监,面谈了一会儿。总监说,我们了解下情况。


我感觉这类情况很严重,没想到公司会这么对待员工。如果不是公司的意思,那么个人行为更恶劣。


结果,HR将情况告知了郭总,让郭总找我聊聊。


我原来以为只是白胖子的个人想法,因为一个花十几万猎头费聘来的大集团高管,不至于境界那么低,偏听偏信,一点技术上的判断力都没有。但是,后来跟郭总一聊发现,他的想法完全受白胖子影响。换句话说,郭就是个傀儡,他也不了解该如何工作,完全听白胖子的。也就是郭当皇帝拿工资,任命白胖子为常务皇帝干活。


郭说,现实情况就是你可有可无。如果你足够听话,我肯定会保你。如果不听话,那么他只能重新招人。


这还有什么理由待下去呢?我提出了辞职。


一开始,白胖子一派很开心,马上就批准我的辞职。后来,他们开始紧张了起来。


据说,白胖子原计划将我搞走后,引入他的认识一个熟人进来。



但是他的人来面试之后,履历不匹配,还要价太高,远超出我的薪资,公司没有同意。结果,“人傻、钱多、速来”的换人计划落空,我又被搞走了,导致AI项目无人接手了。


现在,他们赶紧启动招人,并且尽量拖着不让我走。


这个公司离职交接很快,这是几十年的传统。你一旦提出离职,不管何种岗位,是否有交接人,三两天必定办完手续走人。


但是,我破纪录了。我被卡了半个多月,愣是不给我办离职手续。一催就说,法律规定30天才能走。



这就矛盾了,前期你说我可有可无,是个可怜虫,现在又不让我走。


后来,我就催。我说没活了,还留我干什么?结果他们给我安排改bug的工作。我的AI项目识别率99%,他们测出那识别不了的1%算bug,让我修改。



改不出来,就不办手续。


搞得我都想留下来了,留下来让你们辞退我得了,还能拿赔偿。
最后,多方运动,终于办完了手续。
就在最后运维、财务、人力全部都签完字了,还是不给离职证明,说要改bug到满意为止。



从业这么多年来,没有经历这么恶心的事情。


最后,总算是走了。


一个月后,发了离职工资,金额不对。我找公司专门负责工资核算的员工,打电话不接,加微信不通过。托其他同事的关系,才要到了工资条。后来,他们居然还想问我工作上的问题。



这就是大公司,以及大公司里的人情世故。


后来,也听到很多同事的吐槽,说公司如何如何。



一入职白胖子就会鼓动新人去请领导吃饭,表示站队。我就是没有站队,导致被针对。


还有,一动代码就捅娄子的白胖子,曾经动过一次代码,结果捅了大篓子。导致集团追责,技术部全体员工都被扣了工资。因为白胖子通过口若悬河的说辞,让自己完全撇清了关系。因此部门领导扣了全体同事的,唯独没扣白胖子的。结果,同事找到了Git代码提交记录,发现完全就白胖子自己一个人的疏忽造成的。这就是“集体闹绩效事件”。但是,即便集体闹,也没什么用。


我最反感的是即便大家都知道此人横行霸道,但是大家依然无能为力。


因为这个公司太大了,管事的人太多了,导致都管不了,也改变不了。现实情况是只有老板能管,但是老板很信任他建立的体系。


如果有人把白胖子的事迹告诉老板,那老板会狠批告密者,这叫打小报告,是严重违纪。因为公司有七八个部门,大约上百人专门做人员的评价工作,他们每天的工作就是进行风气整治和文化的净化。


但是,这些部门都知道白胖子的事迹,就算都觉得不对,谁来下这个手?肯定不是自己!这是得罪用人部门的事情。那就等老板知道了,老板发了话,大家才抢着干。但是老板又不让打小报告,永远不会知道。那就是用人部门说了算。用人部门又听白胖子。


所以,最后的结果就是白胖子没人能管得了。


在一个很大的体系里,最大的成本就是管理成本,也就是让这个体系能运转的成本。得有200人做服务才能支撑另外200人能正常上下班。


我的另一个感觉就是,大公司的反应速度太慢了。


我从0到1做一个同样需求的AI项目,我在10人企业只需要1个月,在100人企业需要3个月,而在这里,可能1年都干不完。因为周边的东西太多了。会有太多的部门卡你,有功都来抢,有锅都来甩。开不完的罗圈会,写不完申请,以及数不清的明枪暗箭。咱们是技术人,不是朝堂上的政治家。


我实在是不愿意浪费时间在这些人身上,我更愿去研究AI,研究教育。


而小公司就不一样了。可以直面老板,可以直面客户,可以直面技术。行动迅速敏捷,效率高。


如今的市场变化很快,需要快速响应,需要快速迭代,需要快速试错。新模式的爆发速度,让人猝不及防。


跟着小公司老板有很多可以学习的地方,会亲历一个想法从诞生到落地,这些我全程都会亲历,这很有可能就是我的以后。


随着年龄的增长,越来越不愿意待在能养老的地方,反而愿意去折腾,去挑战。因为剩下的时间不多了。


目前入职了一家小公司,不用打卡,不用写各种汇报材料,不用请领导吃饭,同事间关系简单,老板有活力,有想法,有干劲。中午吃完饭,会去园区里走走,晒晒太阳,听听鸟叫,高效率工作,大家也经常和老板有那种面红耳赤的讨论,这在集团企业内是不敢想的,更有一种独立人的自主感。我所写的代码,客户、同事和自己都满意,这是我非常喜欢的。


我一直是跟着自己的感觉走,从不委屈自己的内心。我一个老领导生病了,心脑血管方面的问题。术后,医生不让他抽烟喝酒。后来,他轻度抑郁。医生开始让他每周不能超过2顿酒,每天不超过3支烟。他问医生,为什么现在又可以了?医生说,相比于抑郁症,抽烟喝酒的伤害更小一些。心情对人体的影响,胜过肉体的伤害。工作十多年,我几乎都是裸辞。找工作也基本不内推,走网上投简历。每次也都找的挺好,下一家总能解决上一家的问题。当然,新一家也会有新的问题,但每次都是迈上一个新台阶。干这行,能进步就好。


不委屈自己的内心,也不委屈自己的能力。一切都有解决方案,未知的变化胜过已知的不变。


期望我现在的公司越来越好。也祝原来的公司蒸蒸日上。


另外,我相信白胖子以后肯定比我混得好,甚至我相信他去另一家公司依然能混得风生水起,但是这并不影响我坚守我自己内心的信念。


这就是各有各的道。我老领导经常召集众兄弟给他帮忙,我们多数也是友情出演。他经常感慨,自己也狠不下心去干一些坑蒙拐骗的活,即便他知道别人干项目就是“要么坑客户,要么坑自己”,他也依然选择自己吃点亏。不然他也能混的风生水起。但是,也正是因为他这么做,他才能召集起来我们这一众兄弟。我们本就不是耍心机的人,因此才愿意向他靠拢。他要变了,虽然我们也很一般,那他身边该换人了。


都有各自的活法,无所谓好坏之分。


作者:TF男孩
来源:juejin.cn/post/7496709980680863744
收起阅读 »

WC!一键微信聊天记录MCP!老板监工神器!

作者:前端开发爱好者 上班经常摸鱼的小伙伴们要注意了,老板们的监工神器来了! ChatLog 是一款开源的聊天记录分析工具,能够帮助用户高效解析、可视化和挖掘聊天数据中的关键信息。 它支持从本地数据库文件获取微信、QQ、Telegram 等主流聊天工具的聊天...
继续阅读 »

作者:前端开发爱好者


上班经常摸鱼的小伙伴们要注意了,老板们的监工神器来了!


ChatLog 是一款开源的聊天记录分析工具,能够帮助用户高效解析可视化挖掘聊天数据中的关键信息。


图片


它支持从本地数据库文件获取微信QQTelegram 等主流聊天工具的聊天记录,并通过智能分析数据可视化等功能,帮助用户更好地管理和利用这些数据。


无论是个人社交分析团队协作优化,还是商业场景的客户对话洞察,ChatLog 都能提供强大的支持。


ChatLog 核心特点



  • 智能分析:自动提取聊天记录中的高频词情感倾向活跃时段等关键指标,帮助用户快速了解聊天内容的核心信息。

  • 多平台支持:兼容微信QQTelegram 等主流聊天工具导出的数据格式,满足不同用户的需求。

  • 数据可视化:生成词云时序活跃图关系网络图等,直观呈现聊天特征,让复杂的数据一目了然。

  • 隐私保护本地化处理数据,无需上传云端,确保信息安全。用户可以放心使用,无需担心隐私泄露。

  • 自动化报告:一键生成分析报告,支持导出 PDF/Excel,便于分享与存档。


如何快速使用


安装 ChatLog


ChatLog 提供了两种方式安装,一种是直接下载预编译版直接安装,另外一种就是下载源码方式安装



go install github.com/sjzar/chatlog@latest

对于大部分人来说,直接使用 预编译版 就能满足大部分需求,除非你需要做二次开发的可以下载源码本地运行


图片


执行 ChatLog 启动 Terminal UI 界面。


图片


使用 ↑ ↓ 键选择菜单项,按 Enter 确认选择,按 Esc 返回上级菜单,按 Ctrl+C退出程序。


MCP 集成指南


运行 ChatLog,完成数据解密并开启 HTTP 服务


以 ChatWise 使用 MCP SSE 为例,


在 URL 中填写 http://127.0.0.1:5030/sse,并勾选 动执行工具,点击 查看工具 即可检查连接 chatlog 是否正常:


图片


测试功能是否正常:


图片


更多 MCP 集成指南 查看https://github.com/sjzar/chatlog/blob/main/docs/mcp.md


“牛马”开始慌了?


在日常工作中,微信等工具已成为“牛马”日常沟通的重要工具。


海量的聊天记录中蕴含着大量有价值的信息,却往往难以高效利用。


图片


ChatLog 的出现,无疑为“牛马”提供了一个强大的工具,可以更高效地管理和分析微信聊天记录。


老板会不会用这个工具来分析我们的聊天记录?


随着 ChatLog 这样的工具出现,不少 “牛马” 开始担心:


老板会不会用这个工具来分析我们的聊天记录?以后摸鱼的时间是不是都没了?


图片


但实际上,ChatLog 的出现更多是为了帮助我们更好地管理自己的聊天记录,提高工作效率。


它可以帮助我们快速总结群聊内容,提取聊天记录中有用的信息,从而更好地完成工作任务。


例如:



  • 快速查找聊天内容:通过关键词搜索,快速定位到重要的聊天记录。

  • 每周工作总结:自动生成聊天记录的总结报告,帮助我们快速回顾本周的工作重点。

  • 提取关键信息:从大量聊天记录中提取关键信息,比如客户的需求、项目进展等,方便我们进行后续的工作安排。


总之,ChatLog 是一款功能强大的开源聊天记录分析工具。


它不仅支持多种主流聊天工具的数据格式,还提供了智能分析、数据可视化和自动化报告生成等功能。



作者:独立开阀者_FwtCoder
来源:juejin.cn/post/7496033842748571698
收起阅读 »

理想正式官宣开源!杀疯了!

最近,新能源汽车制造商「理想汽车」面向业界搞了一个大动作,相信不少同学也看到了,那就是: 正式宣布开源「理想星环OS」操作系统,并且欢迎各位开发者参与验证开源组件的功能和性能。 作为一名开发者和理想车主,说实话第一眼看到这个信息时还是挺意外的,万万没想到,如今...
继续阅读 »

最近,新能源汽车制造商「理想汽车」面向业界搞了一个大动作,相信不少同学也看到了,那就是:


正式宣布开源「理想星环OS」操作系统,并且欢迎各位开发者参与验证开源组件的功能和性能。


作为一名开发者和理想车主,说实话第一眼看到这个信息时还是挺意外的,万万没想到,如今汽车制造商也开始玩开源这一套了。



「理想星环OS」是理想汽车历时3年所研发的汽车操作系统,在车辆中担任“中央指挥官”这一角色,向下管理车辆硬件,向上支撑应用软件。



具体来说,「理想星环OS」包含如下四个组成部分,用于高效调度全车资源并确保汽车功能稳定运行。



  • 辅助驾驶OS(大脑):用于处理复杂的思维过程,以确保辅助驾驶又快又好地工作。

  • 智能车控OS(小脑):用于控制车辆“肢体”,快速执行各种车辆基础控制命令。

  • 通信中间件(神经系统):负责车内各个模块(如刹车、屏幕、雷达)间的高效可靠通信。

  • 信息安全系统(免疫系统):负责数据加密保护以及身份认证和权限管控等信息安全的保障。


星环OS主要组成部分


早在今年3月份的时候,理想汽车CEO李想就曾在2025中关村论坛年会上宣布过,理想汽车自研整车操作系统 ——“理想星环OS”将会开源,而这一承诺终于在最近开始逐步向外兑现。



按照理想官方发布的开源计划时间轴来看,「理想星环OS」的开源将会分为三个阶段来逐步落地。



  • 第一阶段主要是开源星环OS 0.1.0版本,包含安全实时RTOS以及通信总线Lite。

  • 第二阶段开源星环OS 1.0.0版本,包含完整的智能车控系统以及智能驾驶系统基础能力,时间节点为今年的6月30号左右。

  • 第三阶段开源则将会包括完整的智能驾驶系统以及虚拟化引擎,时间节点定在了2025年的7月后。



并且理想承诺,星环OS将会采用宽松型的Apache License,既不会通过开源来收取费用,也不会干涉代码的使用方式,更不会控制使用者的数据。


按照官方的说法,第一阶段的开源目前已经正式兑现,代码已经托管于国内的Gitee平台之上。


出于好奇,我也特地去Gitee平台上搜了一下。


果然,理想汽车已经在Gitee平台上创建了一个名为「HaloOS」的开源组织,里面包含了一阶段开源相关的多个代码仓库和文档仓库。



具体来看,目前的开源代码主要是 智能车控OS(VCOS)通信总线lite(VBSlite) 两大部分,并且其开源仓库划分得非常细,文档是文档,代码是代码,配置是配置,示例是示例。



文档仓库我们以智能车控OS(VCOS)文档为例,其专门搞了一个文档仓库和详细文档说明,并且附有详细的快速跳转链接,大家可以感受一下这个文档仓库的组织风格,还是非常便于开发者使用的。



docs
├── OVERVIEW.md # 项目概述
├── README.md # 文档结构简介(即本文)
├── _static/image # 文档中用到的图片资源
├── api_reference # API参考文档
├── configuration_reference # 配置项参考文档
├── key_technical # 关键技术说明
├── porting # 芯片移植文档
├── quick_start # 快速入门指南
└── user_manual # 开发者手册与详细说明
├── components # 功能组件使用说明
├── kernel # 内核模块文档
└── studio # Studio集成开发环境相关文档

而代码仓库这一块,我们以通信总线lite(VBSlite)工程核心组件之一的MVBS代码仓库为例,仓库说明里给出了详细的代码架构组织,大家也可以感受一下。


mvbs
├── README.md # 这个是MVBS仓库的readme
├── build.mk # 用于构建的makefile文件
├── CMakeLists.txt # cmake编译脚本
├── posix_aux # 为linux和windows平台提供扩展支持库
├── include
│ ├── mcdr # 序列化接口
│ ├── mvbs # MVBS头文件集合
│ │ ├── adapter # 适配层头文件
│ │ ├── core # MVBS内部核心的实体定义和操作
│ │ ├── diag # 诊断相关的头文件
│ │ ├── rte # RTE接口文件
│ │ ├── rtps # RTPS协议元素定义文件
│ │ ├── sections # 用于支持内存layout
│ │ └── utils # 常用的工具文件
│ └── rpc # RPC头文件
└── src
├── adapter # 适配层实现
│ ├── auto # 基于VCOS 适配层的参考实现
│ └── posix # 基于POSIX提供的适配层实现
├── core
│ ├── diag # 诊断工具的实现
│ ├── discovery # 实体发现协议的实现
│ ├── entities # MVBS内部实体的实现
│ ├── include # 提供给MVBS内部的头文件
│ ├── messages # 报文组装的实现
│ ├── mvbs # MVBS内部接口层的实现
│ ├── netio # 网络接口的封装实现
│ ├── qos # E2E和WLP的实现
│ ├── storages # CacheChange和History的实现
│ ├── transport # Transport的实现
│ └── utils # 常用工具的实现
├── mcdr # 序列化库的实现
├── rpc # RPC的实现
└── rte # RTE接口的实现

再看一下具体代码,函数和代码组织都比较宽松,是我个人比较喜欢的风格,另外关键步骤或关键字段设有代码注释,阅读起来也便于理解。



并且仓库里还给出了非常详细的快速入门开发者手册,内容我看了一下,内容甚至从安装 git-repo 工具开始,确实给得非常详细。



追了其中几个比较核心的代码仓库后我们会发现,这几个核心项目源码都是基于C语言来实现的,这也再次说明了 C 语言在某些关键系统中不可撼动的核心地位



大家感兴趣的话也可以上去学习学习相关的代码,研究通了以后想进新能源智能车企做核心系统研发那不就是分分钟的事情了。



众所周知,这两年新能源智能汽车领域的竞争也进入到白热化阶段了,各家新能源车企都在不断地进行产品优化和技术摸高,这个趋势在未来很长一段时间内想必还会继续保持。


按照理想官方的说法,此次开源的主要目的是促进行业合作,旨在破解行业“重复造轮子”的困局,同时通过生态的共建来实现车企之间、车企与其他厂商之间的互利共赢,最终普惠到每个用户。


当然不管他们怎么去说,作为一名开发者我们都清晰地知道,开源的背后其实也是生态的建设和博弈,说实话这一步,理想在新能源车企阵营里走得还是非常超前的。


最近这两年,我自己一直都挺关注新能源汽车市场的,线下也试驾和体验过诸多品牌的新能源汽车产品,也切实感受到了这几年技术和产品的飞速迭代。希望国产智能新能源汽车能持续崛起,为用户带来更多技术普惠和感动人心的好产品。



注:本文在GitHub开源仓库「编程之路」 github.com/rd2coding/R… 中已经收录,里面有我整理的6大编程方向(岗位)的自学路线+知识点大梳理、面试考点、我的简历、几本硬核pdf笔记,以及程序员生活和感悟,欢迎star。



作者:CodeSheep
来源:juejin.cn/post/7503810377554984998
收起阅读 »

待业的两个月,让我觉得独立开发者才是职场的归宿。

前言 今年2月中旬左右因为公司运营的问题,具体原因是缺少版权。毕竟现在的大环境有些刚性的产品,没有版权轻易入场即使可以赚钱,那么这个钱终于不是自己的。 在接到待业通知的时候,既不意外也不慌张。 不意外,是因为工作几年之后都是老江湖,公司能不能支棱起来都是很明...
继续阅读 »

前言


今年2月中旬左右因为公司运营的问题,具体原因是缺少版权。毕竟现在的大环境有些刚性的产品,没有版权轻易入场即使可以赚钱,那么这个钱终于不是自己的。


在接到待业通知的时候,既不意外也不慌张。



  • 不意外,是因为工作几年之后都是老江湖,公司能不能支棱起来都是很明显的状态。不论多大的公司,什么时候开始人力扛把子,抓考勤、搞制度,距离凉不远了

  • 不慌张,是因为从3年前就已经开始准备副业了。最近两年更是经常搞到凌晨1~2点才睡,接到待业通知的时候,被动收益已经是薪资的1.5~2倍的水平了。毕竟,给人打工终究不过是为人做嫁衣,寄人篱下罢了。


未雨绸缪


找方向


都知道短视频是红利,所以基本上短视频已经玩过了。某音现在还有1800多粉丝,头条、UC、百度家号,基本上累计粉丝也有几百个,也写出过几篇10w+的爆款文章


wechat_2025-04-21_170709_618.png


wechat_2025-04-21_170535_331.png


后来发现这个赛道并不好做,1是花费的时间和收入不成比例,2是竞品太多。想脱颖而出难上加难。


尝试过发现,还是得用自己的专业知识变现。1是轻车熟路,2是清楚获量和变现模式,相当于短视频的红海不如给自己打工写自己的App。


经常自我反思,做了那么多产品,应付了那么多需求,有多少是真的为了服务用户?有多少不过是为了应付KPI?有多少不过是满足产品经理的梦?,所以很早之前就开始研究自营产品。 第一年基本上是0收入,勉强把开发账号的688赚回来了。


后来认识了一些志同道合同僚,有想法、有技术,所以一拍即合!王侯将相宁有种乎?


对于一款成功的产品,无法满足三个核心词之一。高频、刚需,痛点,三者得一者得天下!


高频:常见的比如社交、游戏(大型网游、小型休闲)、影视、音频等。


刚需:常见的比如教育、办公打卡、宝宝起名等。


痛点:常见的比如电子衣橱、月子餐、自媒体工具


能落地


这里的能落地从两个方面阐述,1是从产品方向,2是从人的方向。如果是单枪匹马打天下,那大可不用考虑第二点。


产品维度


无论从什么角度切入独立开发者,都要想清楚产品给谁用?赚谁的钱?怎么赚?很多项目出师未捷身先死,大多数并没有找到自己的用户群体,更不用谈赚钱这件事了。


简单来说:准备好了再出发,而不是头脑发热想一出是一出。


人的维度


第一点:谋事在人成事在天,为什么要把人提出来?因为很多常见的合作都需要基于对项目的认可,如果不认可自己正在做点事情,那和打工的心态一样,混日子得过且过。这种很容易消极怠工,也容易半路腰斩


第二点:要有专业的技术能力,确保能为合作保驾护航。因为只有这样才能保障产品正常推进,保证项目平稳落地。


与君共勉


当品尝过自由的味道,大抵很难再适应被束缚的生活。 认清自己的方向和定位,找到适合方向和机遇,毕竟一辈子能够遇到的机遇屈指可数。毕竟现在的大环境,想打工都是一件奢侈的事情,更不要想提高福利待遇了,不过是痴人说梦罢了。


职场终究不过是赚钱赎身,换取早日恢复自由自身的过渡!那些在职场内卷的同行们,没必要,除非你的老板有胖东来的福利待遇。


遵守规则,方得长治久安,最后祝大家大吉大利,今晚过审!


作者:iOS研究院
来源:juejin.cn/post/7495570300123267084
收起阅读 »

程序员危矣!别想着35岁以后还能送外卖

马上35了,没想到公司没能坚持到我35岁下岗,自己先不行了。HR说,我也很想 N+1,可是老板还没来得及跟小姨子跑路,手里的钱只够买一张票给小姨子了,现在就在办公室等着大家去揍他。老板说随便揍,但是要赔医药费和管饭,他已经一天没吃饭了,只需要给他点份外卖就行。...
继续阅读 »

马上35了,

没想到公司没能坚持到我35岁下岗,

自己先不行了。


HR说,我也很想 N+1,

可是老板还没来得及跟小姨子跑路,

手里的钱只够买一张票给小姨子了,

现在就在办公室等着大家去揍他。

老板说随便揍,

但是要赔医药费和管饭,

他已经一天没吃饭了,只需要给他点份外卖就行。


想着之前领了几年的窝囊费,现在是时候反哺一下了。

于是点了2份杨铭宇黄焖鸡,给自己也点一份,

吃饱了跟老板复盘下他怎么是把公司干垮的,

顺便让他见识下我的组合拳。


结果外卖小哥出门的时候不但不帮我带走垃圾,

还脱下黄马褂往地上一扔,说脑子不干了!

我莫名其妙,

我是要找老板算账,又没惹他,他这是怎么了。

他留下三个字潇洒而去:东哥在召唤!


看到新闻我似乎理解了:


老板见我给他送去外卖很是感动,

说小王啊,以后你就是我王哥,

我有一个东山再起的计划,等我吃饱了我跟您讲,

我打断他:你的饼都喂不饱自己,还是赶紧把你王哥工资发了,

不然一会儿你身上会有很多痛点。


老板说授人以鱼不如授人以渔,

工资给你花了就没了,不如我送你一辆电动车,

刚好刚刚的外卖骑手不干了,

这正是你黄袍加身的好时机,我看好你,你可要好好把握啊!

你看你,也快35了吧?

毕业干的几个项目大部分都流产了,甚至公司都黄了。

你这简历都不好写,

怎么竞争的过应届生?

现在工作也不好找,

送外卖才是最佳职业归宿,

穿黄色衣服又不是绿色的,有什么不能接受的?

实在不行也可以穿蓝色,或者红色的,

东哥最近也在招人,我给你内推下?

好歹也算进了大厂你说是不是!

今天你请我吃黄焖鸡,兄弟我非常感动,

我要送你一辆电动车,

让你以后天天能送黄焖鸡……


等等,

我不是来揍他的吗?

怎么又被PUA了?


不过话说回来,

大龄程序员找不到工作怎么办?

外卖骑手能不能干?

东哥的召唤是不是一个机会?


经过我不依赖 deepseek 的深度思考,

得出以下结论:

程序员危矣,

外卖骑手只是商业大佬开疆拓土的马前卒。


表面上是维护外卖骑手的权益,

实际上骑手只是商业竞争中的一枚棋子。


未来低空经济下的外卖行业并没有骑手参与的环节,

无人机派送成本微乎其微,甚至一路上还能给企业带点广告收入。


如今各位互联网大哥争夺的骑手,

短短几年又会成为被抛弃的对象。

别人真正要的不是骑手,

而且分食外卖蛋糕的刀叉。


商家处境也好不到哪里去,

当年轻人都习惯了预制菜,

廉价机器人都可以胜任预制菜的加热,

无人机派送,全程无人工参与,又卫生又快。


谁说京东只能送快递了?

投入的无人机要充分利用起来啊,

超市闪送、外卖到家,对它来说无缝接入啊。

只是你点外卖不会去他那里下单这让东哥很头疼,

占据市场后,降本增效的第一步就是针对骑手,

其次就是商家,为什么商家可以用预支包官方不能呢?

官网机器人餐厅将是又一次降本增效的尝试。


当所有的成本都将被压缩为电力成本,

这收益可能不比超级电商少吧,

何况收益模式可以随时定制:

无人机空中文字广告、

取餐点对点视频广告、

用户充值黄金会员免看一分钟广告。


几年后,

曾经的外卖小哥放下手中的砖,

吃着从无人机上取下午餐,

会发现还是熟悉的互联网味道,

而自己曾经就是这外卖商业帝国最底层的一块砖……

收起阅读 »

只写后台管理的前端要怎么提升自己

本人写了五年的后台管理。每次面试前就会头疼,因为写的页面除了表单就是表格。抱怨过苦恼过也后悔过,但是站在现在的时间点回想以前,发现有很多事情可以做的更好,于是有了这篇文章。 写优雅的代码 一道面试题 大概两年以前,面试美团的时候,面试官让我写一道代码题,时间单...
继续阅读 »

本人写了五年的后台管理。每次面试前就会头疼,因为写的页面除了表单就是表格。抱怨过苦恼过也后悔过,但是站在现在的时间点回想以前,发现有很多事情可以做的更好,于是有了这篇文章。


写优雅的代码


一道面试题


大概两年以前,面试美团的时候,面试官让我写一道代码题,时间单位转换。具体的题目我忘记了。


原题目我没做过,但是我写的业务代码代码里有类似的单位转换,后端返回一个数字,单位是kb,而我要展示成 KBMB 等形式。大概写一个工具函数(具体怎么写的忘记了,不过功能比这个复杂点):


function formatSizeUnits(kb) {
let units = ['KB', 'MB', 'GB', 'TB', 'PB'];
let unitIndex = 0;

while (kb >= 1024 && unitIndex < units.length - 1) {
kb /= 1024;
unitIndex++;
}

return `${kb.toFixed(2)} ${units[unitIndex]}`;
}

而在此之前,是一个后端同学写的代码(说起来,后台管理系统前端人力不够后端帮忙写好像是常规操作,后端总觉得写前端简单,而我只能说你们那代码写的,一言难尽……),如下:


function formatSizeUnits(kb) {
var result = '';

if (kb < 1024) {
result = kb + ' KB';
} else if (kb < 1024 * 1024) {
result = (kb / 1024).toFixed(2) + ' MB';
} else if (kb < 1024 * 1024 * 1024) {
result = (kb / 1024 / 1024).toFixed(2) + ' GB';
} else {
result = (kb / 1024 / 1024 / 1024).toFixed(2) + ' TB';
}

return result;
}

虽然功能都一样,但是我写在面试的时候写了上面的代码得到了面试官的赞扬,也因此非常顺利的通过了面试。而如果我写成了下面的样子,估计不会有这种效果。


如何提升代码质量


想提升代码质量,最理想的是靠 code review ,但实际上这玩意在大多数公司根本就不存在。其次就只能多看看大佬们写的代码,但是一来后台管理本来就没太大难度很少有大佬,二来很多时候一个后台管理系统就一两个人负责。


还好现在有了各种 AI 工具,可以非常方便的优化自己的代码了。


还是上面的问题,看看 GPT 给的答案


// 提问:写一个工具函数,对文件大小的单位进行转换,加注释
// 回答:下面是一个JavaScript工具函数,它接受文件大小、初始单位、目标单位和小数位数,然后返回目标单位下的文件大小。

/**
* 将文件大小从一个单位转换为另一个单位。
*
* @param {number} size 文件大小。
* @param {string} fromUnit 初始单位('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')。
* @param {string} toUnit 目标单位('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB')。
* @param {number} [decimalPoint=2] 结果保留的小数位数,默认为2。
* @return {string} 转换后的文件大小,带单位。
*/

function convertFileSize(size, fromUnit, toUnit, decimalPoint = 2) {
// 定义单位与字节之间的转换关系
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
// 获取初始单位和目标单位的索引
const fromIndex = units.indexOf(fromUnit);
const toIndex = units.indexOf(toUnit);

// 如果单位不在列表中,抛出错误
if (fromIndex === -1 || toIndex === -1) {
throw new Error('Invalid units');
}

// 计算初始单位与目标单位之间的转换系数
const exponent = toIndex - fromIndex;
// 计算结果大小
const resultSize = size / Math.pow(1024, exponent);

// 返回格式化后的结果
return parseFloat(resultSize.toFixed(decimalPoint)) + ' ' + toUnit;
}

// 示例使用
console.log(convertFileSize(1, 'GB', 'MB')); // 输出: 1024.00 MB
console.log(convertFileSize(1, 'MB', 'KB')); // 输出: 1024.00 KB
console.log(convertFileSize(1, 'KB', 'B')); // 输出: 1024.00 B
console.log(convertFileSize(1, 'MB', 'GB', 5)); // 输出: 0.00098 GB

还能说什么,我只能说 NB!(经评论区提示,此段代码可能有问题,建议大家在使用AI工具时,重点是借鉴思路,直接使用代码需要谨慎~)


我现在每次写大段逻辑之后都习惯拿给 AI 看看,有什么更好的实现方式,或者用什么设计模式。AI 是非常低成本且高效提升代码质量的工具。


学会封装


一个功能用到了好多次,为什么不封装成组件?一个组件用到了好几个项目,为什么不单独写个npm包?差不多的项目创建了好几个,为什么不封装成脚手架?


你说,没时间,没必要,复制粘贴反而更快。


那你就完全没理解,这么做不一定是为了让工作更快完成,而是可以让你在年年终述职时更有话说(你就算写了一百个表单表格没有写一个脚手架更值得炫耀),如果不会写可以问问 AI。


而当你真正开始封装组件,开始写工具库了,你会发现你需要思考的确实比之前多了。


关注业务


对于前端业务重要吗?


相比于后端来说,前端一般不会太关注业务。就算出了问题大部分也是后端的问题。


但是就我找工作的经验,业务非常重要!


如果你做的工作很有技术含量,比如你在做低代码,你可以面试时讲一个小时的技术难点。但是你只是一个破写后台管理,你什么都没有的说。这个时候,了解业务就成为了你的亮点。


一场面试


还是拿真实的面试场景举例,当时前同事推我字节,也是我面试过N次的梦中情厂了,刚好那个组做的业务和我之前呆的组做的一模一样。



  • 同事:“做的东西和咱们之前都是一样的,你随便走个过场就能过,我在前端组长面前都夸过你了!”

  • 我:“好嘞!”


等到面试的时候:



  • 前端ld:“你知道xxx吗?(业务名词)”

  • 我:“我……”

  • 前端ld:“那xxxx呢?(业务名词)”

  • 我:“不……”

  • 前端ld:“那xxxxx呢??(业务名词)”

  • 我:“造……”


然后我就挂了………………


如何了解业务



  1. 每次接需求的时候,都要了解需求背景,并主动去理解


    我们写一个表格简简单单,把数据展示出来就好,但是表格中的数据是什么意思呢?比如我之前写一个 kafka 管理平台,里面有表格表单,涉及什么 cluster controller topic broker partition…… 我真的完全不了解,很后悔我几年时间也没有耐下心来去了解。


  2. 每次做完一个需求,都需要了解结果


    有些时候,后台管理的团队可能根本没有PM,那你也要和业务方了解,这个功能做了之后,多少人使用,效率提高了吗?数据是怎样的?


  3. 理解需求,并主动去优化


    产品要展示一千条数据,你要考虑要不要分页,不分页会不会卡,要不要上虚拟表格?


    产品要做一个可拖拽表单,你要考虑是否需要拖动,是否需要配置。


    其实很多时候,产品的思维可能会被局限在竞品的实现方式,而前端可以给TA更多选项。在和产品沟通的时候,你不仅是沟通页面的实现,也更能理解业务。



关注源码


说到源码, Vue,React 这些基本是每次必问,也有太多大佬们的总结我就不多说了。


除此之外,我想大家每次面试应该都会被问,你写了什么亮点的项目,困难的项目,你会说什么?哦,都是表单表格,都用 Element UI 实现的,没什么难度。那估计你面试也就到这里了。


那说什么,后台管理就这些啊?!


如果你用了 Element UI 你可以说写了什么自定义 Element UI 表单组件,Element UI 表单源码是什么原理,怎么通信的?用了 Axios 可以说 Axios 的原理,它的拦截器怎么实现的?用了编辑器 diff 那你知道 diff 算法是什么吗?用了 ECharts 那你知道他底层是用什么绘制的吗?用了 husky ?husky的原理是什么?用了Vite,它为什么快?是怎么打包的?写过插件吗?


可能有人觉得我离谱,事实上上面每一个问题都是我在面试中真实被问到的。当然,如果全部去了解,肯定不现实,每个人的精力有限,不可能每个用到的每个工具每个库都去了解原理,不过只要有一两个你去了解过,就可以在面试中引导面试官来问,要学会表现出你擅长的点


至于怎么读源码?以前我不知道,现在嘛…… 为什么不问问神奇的 ChatGPT 呢?



讲一下 Axios 源码中,拦截器是怎么实现的?


Axios 的拦截器实现基于 Axios 的核心原理,即 Axios 实例是一个包含请求和响应拦截器堆栈的对象。当发出请求或接收响应时,Axios 会遍历这些拦截器,并按照添加的顺序执行请求拦截器,以及按照相反的顺序执行响应拦截器。


在 Axios 的源码中,拦截器是通过一个 AxiosInterceptorManager 实例来管理的,它维护了一个拦截器数组。每个拦截器都是一个包含 fulfilledrejected 函数的对象。这两个函数分别对应于拦截器成功处理和拦截器处理出错的情况。


以下是 Axios 拦截器管理器的一个简化版本,展示了其核心实现思路:


class InterceptorManager {
constructor() {
this.handlers = []; // 存储拦截器的数组
}

use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1; // 返回拦截器的ID
}

eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null; // 移除拦截器
}
}

forEach(fn) {
this.handlers.forEach((h) => {
if (h !== null) {
fn(h);
}
});
}
}

在发送请求或接收响应时,Axios 会创建一个 promise 链,并通过 forEach 方法将拦截器中的 fulfilledrejected 函数添加到这个链中。这样,每个拦截器都可以对请求或响应进行处理,然后将结果传递到链的下一个拦截器,或者在出错时结束链的执行。


axios.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});

axios.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});

在 Axios 的完整实现中,这个拦截器机制被集成到了 Axios 的请求发送和响应处理流程中。通过这种方式,Axios 可以在发送请求之前和接收响应之后,但在用户定义的 .then.catch 执行之前,插入自定义的逻辑。


请注意,这里提供的代码只是为了说明 Axios 拦截器的实现原理,并不是 Axios 源码的完整复制。如果你对 Axios 的拦截器实现细节感兴趣,建议查看 Axios 的官方 GitHub 仓库中的源码。



前端基建


当我们工作时间久了面试难免会遇到这些问题,前端工程化,前端监控,工作流,部署,性能等等。其实我们在工作中绝大部分时间都在写代码,对于这些不是所有人都有机会接触到,不过这些和所做的业务无关,是我们提升自己很好的一个思路。


技术选型


技术栈选 Vue 还是 React?Vue 选 Vue2 还是 Vue3?组件库选 ElementUI 还是 Ant Design?微前端有没有使用过?打包工具用 Vite 还是 Webpack?有那么多表单怎么实现的,有没有什么表单配置化方案,比如Formily?


对于我这种菜鸡,我这种只写简单的表单表格的人,这些都……无所谓……


image.png

不过为了应对面试我们还是需要了解下未选择技术栈的缺点,和已选择技术栈的优点(有点本末倒置…但是常规操作啦)


Vue 你可以说简单高效轻量级,面试必会问你为什么,你就开始说 Vue 的响应式系统,依赖收集等。


React 你可以说 JSX、Hooks 很灵活,那你必然要考虑 JSX 怎么编译, Hooks 实现方式等。


总体而言,对于技术选型,依赖于我们对所有可选项的理解,做选择可能很容易,给出合理的理由还是需要花费一些精力的。


开发规范


这个方面,在面试的时候我被问到的不多,我们可以在创建项目的时候,配置下 ESlintstylelintprettiercommitlint 等。


前端监控


干了这么多年前端,前端监控我是……一点没做过。


image.png

前端监控,简单来说就是我们在前端程序中记录一些信息并上报,一般是错误信息,来方便我们及时发现问题并解决问题。除此之外也会有性能监控,用户行为的监控(埋点)等。之前也听过有些团队分享前端监控,为了出现问题明确责任(方便甩锅)。


对于实现方案,无论使用第三方库还是自己实现,重要的都是理解实现原理。


对于错误监控,可以了解一下 Sentry,原理简单来说就是通过 window.onerrorwindow.addEventListener('unhandledrejection', ...) 去分别捕获同步和异步错误,然后通过错误信息和 sourceMap 来定位到源码。


对于性能监控,我们可以通过 window.performancePerformanceObserver 等 API 收集页面性能相关的指标,除此之外,还需要关注接口的响应时间。


最后,收集到信息之后,还要考虑数据上报的方案,比如使用 navigator.sendBeacon 还是 Fetch、AJAX?是批量上报,实时上报,还是延迟上报?上报的数据格式等等。


CI/CD


持续集成(Continuous Integration, CI)和 持续部署(Continuous Deployment, CD),主要包括版本控制,代码合并,构建,单测,部署等一系列前端工作流。


场景的工作流有 Jenkins、 Gitlab CI 等。我们可以配置在合并代码时自动打包部署,在提交代码时自动构建并发布包等。


这块我了解不多,但感觉这些工具层面的东西,不太会涉及到原理,基本上就是使用的问题。还是需要自己亲自动手试一下,才能知道细节。比如在 Gitlab CI 中, Pipeline 、 Stage 和 Job 分别是什么,怎么配置,如何在不同环境配置不同工作流等。


了解技术动态


这个可能还是比较依赖信息收集能力,虽然我个人觉得很烦,但好像很多领导级别的面试很愿意问。


比如近几年很火的低代码,很多面试官都会问,你用过就问你细节,你没用过也会问你有什么设计思路。


还有最近的两年爆火的 AI,又或者 Vue React的最新功能,WebAssembly,还有一些新的打包工具 Vite Bun 什么的,还有鸿蒙开发……


虽然不可能学完每一项新技术,但是可以多去了解下。


总结


写了这么多,可能有人会问,如果能回到过去,你会怎么做。


啊,我只能说,说是一回事,做又是另一回事,事实上我并不希望回到过去去卷一遍,菜点没关系,快乐就好,一切都是最好的安排。


image.png

作者:我不吃饼干
来源:juejin.cn/post/7360528073631318027
收起阅读 »

你见过的最差的程序员是怎样的?

我见过的最差程序员,差到让整个团队崩溃 作为一名在嵌入式领域摸爬滚打近十年的老兵,我见过太多奇葩程序员了。但要说最差的,非"赵工"莫属。 初见赵工 那是我从机械调剂到电子部门的第二年,公司接了个重要项目,需要开发一款基于STM32的工业控制系统。领导从总部借来...
继续阅读 »

我见过的最差程序员,差到让整个团队崩溃


作为一名在嵌入式领域摸爬滚打近十年的老兵,我见过太多奇葩程序员了。但要说最差的,非"赵工"莫属。


初见赵工


那是我从机械调剂到电子部门的第二年,公司接了个重要项目,需要开发一款基于STM32的工业控制系统。领导从总部借来一位"资深嵌入式专家"——赵工。


初见赵工时,他西装革履,一副成功人士模样。"我做过BAT核心项目,对单片机开发了如指掌",他面试时的豪言壮语,让领导对他寄予厚望。


"独特"的编码风格


接手项目的第一周,赵工就展示了他的"实力":


void Do_Something(void)
{
u8 a;
u8 b;
u8 c;
u8 i;
u8 j;
u8 k;
a=1;
b=2;
if(a==1)
{
for(i=0;i<10;i++)
{
if(b==2)
{
k = i + 1;
//do something here
}
}
}
}

没错,这就是他的编码风格——变量命名全是单字母,没有注释,缩进混乱,函数名毫无意义。当我问他这些变量代表什么意思时,他瞪了我一眼:"代码就是写给机器看的,能运行就行,哪那么多讲究?"


"高效"的调试方法


赵工的调试方法更是"高效"。有一次系统死机,排查原因时,他直接往代码里塞了几十个printf:


printf("here1\n");
if(temp > 50) {
printf("here2\n");
control_valve();
printf("here3\n");
}
printf("here4\n");

任何正常程序员都会使用条件断点或日志系统,但他偏要用这种原始方法。更可怕的是,调试完成后,这些垃圾代码常常被他忘记删除,留在生产代码中。


"革命性"的存储管理


记得有次他在处理EEPROM存储时,创造了这样的"杰作":


// 存储用户配置
void save_config(void)
{
// 直接从0地址开始写,不管有没有其他数据
EEPROM_Write(0, (uint8_t*)&global_config, sizeof(global_config));
}

// 加载配置
void load_config(void)
{
// 没有任何校验,直接读取
EEPROM_Read(0, (uint8_t*)&global_config, sizeof(global_config));
}

没有地址规划,没有数据校验,没有版本管理。当我提醒他这会导致数据混乱时,他不以为然:"又不是大型系统,用不着那么复杂。"


结果可想而知,产品一上线,用户配置经常莫名其妙丢失或混乱。


"高级"的内存管理


在一个需要处理大量传感器数据的模块中,他写出了这样的代码:


void process_sensor_data(void)
{
// 每次分配固定大小,用完不释放
uint8_t *buffer = malloc(1024);

// 处理数据...

// 没有free操作
}

这个函数每分钟会被调用几十次,内存泄漏严重。当系统运行几小时后必然崩溃。我指出这个问题时,他竟然说:"单片机会自动回收内存的,不用担心。"


我当时就懵了,这种基础常识都不懂,他是怎么通过面试的?


"创新"的版本控制


提到版本控制,赵工也有独到见解。公司用Git管理代码,他却坚持用自己的方式:



  1. 从不写commit信息,或者就写个"update"

  2. 本地修改后直接push到master分支

  3. 代码出问题了,就复制整个项目文件夹重命名为"project_backup_0415"


有一次他把整个主分支代码弄坏了,急得团队其他成员直冒冷汗。当问他为什么不用分支开发时,他理直气壮:"那太麻烦了,我一个人开发用不着那些东西。"


"高超"的团队协作


赵工的团队协作能力堪称一绝。记得有次我接手他的一个模块进行扩展,打开代码后惊呆了:


// 神秘函数
void xyz(void)
{
u16 m = get_value();
if(m > 30)
{
op();
}
else if(m <= 30 && m > 20)
{
op2();
}
else
{
if(flag)
{
op3();
}
}
}

完全看不懂这函数是干什么的!没有文档,没有注释,变量名全是缩写,函数名毫无意义。我只好硬着头皮找他问。


他却说:"代码写出来就是给机器看的,你看不懂是你水平问题。再说了,这是我的核心竞争力,如果写得太清楚,公司还要我干嘛?"


这种"核心竞争力"理论让我哭笑不得。在我看来,真正的核心竞争力是创造价值的能力,而不是制造混乱的能力。


灾难的项目结局


最后这个项目如何收场?你们猜到了。


原定三个月的项目拖了半年,客户不断投诉系统不稳定。在一次重要演示中,系统当场崩溃,客户大怒。公司损失了一个重要客户,也赔了一大笔违约金。


赵工却毫不愧疚,反而抱怨环境问题:"肯定是测试环境不对,我本地运行得好好的。"


最终,他被公司礼貌地送回了总部,项目由我和另外两位同事重构。我们花了两个月才把这烂摊子收拾干净。


反思:什么造就了"最差程序员"


回想这段经历,我总结赵工这类"最差程序员"的特质:



  1. 技术傲慢:自以为是,不接受批评,拒绝学习新知识

  2. 基础薄弱:缺乏编程基本素养,连最基础的内存管理、代码规范都不遵守

  3. 自私封闭:视代码为个人财产,故意设置理解障碍

  4. 责任推卸:问题永远是别人的,从不反思自己

  5. 短视功利:只关心眼前能跑,不考虑长期维护


这种程序员不仅技术差,更可怕的是态度差。他们像一颗定时炸弹,迟早会给团队和产品带来灾难。


与之对比:什么是好程序员


我27岁进入世界500强外企时,遇到一位让我敬佩的技术主管李工。他的代码风格截然不同:


/**
* @brief 处理温度传感器数据并控制阀门
* @param temperature 当前温度值(摄氏度)
* @return 操作是否成功
* @note 当温度超过临界值时,会自动关闭阀门
*/

bool processTempAndControlValve(float temperature)
{
// 安全检查
if (!isSensorValid(SENSOR_TEMP)) {
logError("Temperature sensor not valid!");
return false;
}

// 温度过高,关闭阀门
if (temperature > CRITICAL_TEMP_THRESHOLD) {
logWarning("Critical temperature detected: %.2f°C", temperature);
return closeValve(VALVE_MAIN);
}

// 正常温度范围
return true;
}

他的代码:



  1. 命名清晰,一看就懂

  2. 有完善注释和文档

  3. 考虑异常情况

  4. 模块化,便于测试和维护

  5. 遵循团队代码规范


更重要的是,他从不吝啬分享知识。每周五下午,他都会组织技术分享会,讲解嵌入式Linux的各种难点。正是在他的影响下,我开始自学Linux,并在28岁时开始写技术公众号分享所学。


职场启示:远离"赵工",培养好习惯


这些经历让我深刻认识到,成为好程序员不仅关乎技术,更关乎态度和习惯。这也是我30岁创业后,在培训和咨询中一直强调的核心理念。


在我的小公司里,我们有严格的代码审查制度,无论资历高低,代码必须符合规范才能合并。有位刚入职的年轻人抱怨:"写那么多注释太浪费时间了!"我给他看了赵工项目的代码和我们后来重构的对比,他立刻理解了。


好的编程习惯就像复利,短期看不到效果,长期却能造就天壤之别。这也是我从嵌入式开发一路走来的深刻体会。


结语


如果你在团队中遇到了"赵工"式的程序员,请保持警惕,远离这种技术债务制造机。如果你担心自己可能有类似倾向,请反思并改变,这对你的职业生涯至关重要。


真正的编程高手,不仅代码写得好,更能让团队变得更好。就像我在二线城市靠技术和分享积累第一个百万时所感悟的:技术能力决定下限,协作能力决定上限。


作为一个从机械转行到嵌入式的非科班程序员,我深知基础扎实和态度端正的重要性。希望每位程序员都能远离"最差",走向更好的自己。


你们遇到过什么样的奇葩程序员?欢迎在评论区分享,我们一起吐槽一下。


另外,想进大厂的同学,一定要好好学算法,这是面试必备的。这里准备了一份 BAT 大佬总结的 LeetCode 刷题宝典,很多人靠它们进了大厂。



刷题 | LeetCode算法刷题神器,看完 BAT 随你挑!


有收获?希望老铁们来个三连击,给更多的人看到这篇文章


推荐阅读:



欢迎关注我的博客:良许嵌入式教程网,满满都是干货!


作者:良许Linux
来源:juejin.cn/post/7489488440113692724
收起阅读 »

当上小组长的第3天,我裁掉了2年老员工

前言 这周末和上上公司的小伙伴小酌一杯,获悉了两则消息,一则好消息,一则坏消息。 好消息是他晋升了,当了个小组长,管了4个人。 坏消息是他需要优化掉组内一个人。 征得本人同意,本文以他的视角来回顾这个魔幻的一周。 职业之殇 20年刚毕业那会,怀着满腔热情进入了...
继续阅读 »

前言


这周末和上上公司的小伙伴小酌一杯,获悉了两则消息,一则好消息,一则坏消息。

好消息是他晋升了,当了个小组长,管了4个人。

坏消息是他需要优化掉组内一个人。

征得本人同意,本文以他的视角来回顾这个魔幻的一周。


职业之殇


20年刚毕业那会,怀着满腔热情进入了某互联网公司,成为了人见人爱的前端CV仔,一心想要造出几个叫得上名字的轮子,也幻想着某天别人称呼我为轮子哥。



good.gif


人在怀揣梦想的时候感觉总有使不完的劲,工作中捣鼓了一些轮子,也在公司内部使用了,虽然有些Bug,但瑕不掩瑜,没有哪个轮子出来就是完美的,慢慢优化就是了。

然而天不遂人愿,公司因为一些不可说的原因,业务没法继续开展,它倒闭了,算上上一份实习的公司,这已经是我干垮的第二家公司了。

后来同事们戏称:"XX,你没当成轮子哥,却成了垮司哥"

我:"..."



sleep.gif


突然晋升


23年的行情你们是知道,还好前端的中级岗位还算比较多。

是的,我又入职了新公司。

前端有十个人,只有一个领导,姑且叫B吧。

与我同一年入职的还有2个小伙伴,其中一个是C。


平淡的日子没啥可留恋的,今天就是昨天复刻。

前几天下午,B突然钉钉发消息给我,还DING了一下,让我到会议室聊一下。

当时感觉挺诧异的,平时虽然也有消息往来,但从来没有单独约谈过,难道有什么坏消息?难道要干掉我了?思绪百转千回。


进了会议室就看到B正襟危坐面对着Mac笔记本,让我做到他对面,他的键盘声时不时想起。



B:是这样子的,你来公司快两年了,这段时间你的产出也是有目共睹的,技术也不错。现在团队内人也比较多,我一个人忙不过来,因此我向领导推荐你当前端的小组长,这事你觉得如何?

我:额,有点突然,可我之前没管过人呢?

B:凡事都有第一次,而且这次你管的人也不多,我们分成两个组,一个是我带,另一个是你带。你只需要管住你底下的4个人就好。

我:那我管哪几个人呢?

B:某某某...,这几个平时相处怎么样?

我:哦哦,这几位老哥我都是比较熟,平时也经常一起吃饭什么的,还好说话。

B:嗯,你回去先考虑一下,确定了明天就会发正式通知。

我:好的。



当B说出让我到小组长的瞬间,其实我已经接受了,没啥好考虑的,毕竟我之前没当过,也跃跃欲试。

接下来的几天,因为这事开心了不少,感觉每天都不一样...



image.png


裁员广进


过了三天,周五下午,又是B找我到会议室聊。



B:通知下来,组织架构变了,角色切换得咋样了?

我:还好啊,还是在做以前的事。

B:你现在是小组长了,算是管理了,管、理需要并进。

B:组内的同事工作了解的怎么样了?

我:还好吧,我们平时工作都有交集,大概知道他们在弄什么。

B:你觉得C怎么样,我需要真实的想法?

我:C和我同一年来的,工作年限比我长,技术也可以啊。

B:C技术比你如何?

我:额,各有千秋吧,侧重点不一样。

B:C招进来的时候工资比较高,但他的工资没有匹配他的产出,你看平时他也不怎么加班,很多时候到点就走,不像其他的同事有干劲,感觉他的积极性、主动性都不怎么强。

我:听说C的媳妇最近怀孕了,父亲也因病住院了,可能比较忙。

B:我们不说理由,只管结果,上头最近在盘点人力,前端需要走一个人,这个名额我倾向落到C,你找他谈谈。公司的底线是赔1个月,不能再多。

我:但他的绩效没问题啊,不是应该n+1吗?

B:他去年Q4得的是E,今年Q1再给一个E,两个E就可以因为绩效低而少给赔偿,之前其它部门也是有这种先例,Q1的E我倾向给他背,你来操作一下,理由要写的有理有据。

我:4月就准备发年终奖了(普遍1个月),是不是发了之后再让他走。

B:不可能,就是要在年终发之前给他赔偿,你只管通知他,具体会有人事去说。

我:...



走出会议室,我的心情是拔凉拔凉的,心想:资本果然是邪恶的,充满了算计。

整个下午我都在犹豫怎么和C开口,代码都没写几行。

犹豫着告诉了他这条消息,他会不会周末就过不好。

犹豫着告诉了他这条消息,他会不会记恨我,毕竟经常一起吃饭也互加了微信好友。

犹豫着告诉了他这条消息,组内的其他同事怎么看我...


最终我还是将B的想法告诉了C,全程我没怎么敢看C的眼睛,我怕看到他失落的眼神。

没想到的是C听到这消息还很平静,只说了一句:



公事公办,好聚好散



尘埃落定


我不知道C的周末怎么过的,我也不知道C最终和人事咋谈的,但结局已注定,C肯定要走。

期间我和B也争取了。



我:C还是比较有经验的,有些疑难问题还得靠他,而且平时对待工作也是蛮负责的。

B:我们不看态度,只看结果,他性价比不高。现在的疑难问题问AI就可以了,他走了我们再招一个新人,哪怕是实习生也可以在AI的帮助下胜任工作,还解决了一半多的成本。

我:C手里还有负责的比较重要的工作怕是不好分出来。

B:这会就要体现出你水平的时候了,该怎么平稳交接,我只要一个结果,记住必须是正向的结果。管理管理,就是管和理,既要管人(管人的行为),也要理人(修理人,让他走)。在公司工作就是要以公司的利益为准。我就是一个比较纯粹的人,只对事不对人,只做对团队对公司有益的事,其他的放第二位。

我:心想:泥马,价值观都出来了,我还能说啥...



经过这事,把刚当上小组长的喜悦心情基本冲没了,有时候我在想:



人和人都是有差距的,屁股决定脑袋,不要轻信别人,也不要总是试图说服别人。




image.png


你在工作过程中会遇到哪些冲击三观的事?说出来让大家涨涨姿势。


作者:小鱼人爱编程
来源:juejin.cn/post/7487210421209186355
收起阅读 »

IT外传:老技术部的困境

它像一个锈迹斑斑的铁柱,挪了它,会立马塌一片房。不挪它,又不敢在上面推陈出新。如今是一边定钉子加固,一边试探着放一把椅子,太难了…… 年会如期进行,在今年严峻的经济形势下,公司今年的营收和利润,相比去年都有大于30%的增长。这主要得益于老板有个原则:员工要比...
继续阅读 »

它像一个锈迹斑斑的铁柱,挪了它,会立马塌一片房。不挪它,又不敢在上面推陈出新。如今是一边定钉子加固,一边试探着放一把椅子,太难了……



年会如期进行,在今年严峻的经济形势下,公司今年的营收和利润,相比去年都有大于30%的增长。这主要得益于老板有个原则:员工要比公司挣得多。也就是今年公司增幅10%,员工收入也要比去年增10%。但是,这个增长不是针对所有人,而是那些挣钱的部门


老板拉来一堆现金,在年会现场分发。张三,3万;李四,13万;王五25万。销售1部,10万;客服2部,5万……很遗憾,IT研发部,不管是团队还是个人,都榜上无名。


不得不说,确实存在这么一个现象,销售类的岗位是盈利部门,像行政、人力、财务这类属于成本部门。而研发类的岗位,则视情况而定。可以是盈利部门,也可以是成本部门。


这个技术部几十个人,其中老员工很多。这里说的老员工,一方面是指在公司待得久,入职七、八年的大有人在。另一方面,年龄也都很大,40岁的也不在少数。公司很重视老员工,常将入职10多年的立为榜样,这让新员工入职后,感到不可思议以及安全感十足。


很多技术部老人看到发奖金,都会很失落。他们说,每年都这样,热闹是别人的,和自己没关系,连保洁、保安都有个“勤勤恳恳奖”,而程序员啥都没有。干技术没有前途。


作为刚入职的员工,我了解的不是很多,不过也稍微有点旁观者的视角。


公司对于技术部很有成见。各个部门也都有意见,尤其是老板。首先体现在系统的脆弱性上,基本上每年在最关键的营销活动时,服务都会宕机。每次宕机,老板都很着急,事后想让技术部避免此类情况再次发生。而技术部每次都有理由,也会提出新的解决方案。 老板配合技术部,从云服务器改为自建机房,从自建机房又迁移上云服务。


我来公司后,经历过两次宕机。第一次是一个大型活动,技术部说本来是没事的,结果因为运营人员在活动还没结束,就登上后台去查看汇总数据。这个汇总,会导致大量实时计算,结果数据库就顶不住了,停服务也停不掉,死机后数小时才重启成功。


领导说既然是数据库差,那就买数据库。技术部讨论后,感觉不能买。买多少?如果买了之后,还出现问题,那么就会处于舆论的被动面


第二次,不算是宕机,只是限流。就是很多人来访问,将一部分人挡在外面。体现在app上是一直弹出500错误、服务器内部错误的提示。弄得营销人员都不敢推广了。来了很多人,进不了门,错失很多客源,浪费了营销成本


后来,技术部又开始总结。原因是APP在一个页面调用了12个不同的接口,而且还有一个接口被连续调用了35次。这导致数据库压力加大,直接100%。幸好禁止用户访问,才没有崩溃。


技术部总监很着急。但是这个总监是App开发出身,不了解服务端。服务出问题了,他就去找后端开发。后端开发者感觉,架构设计是你总监的事情。我就算干好了,那也是你的功劳。因此不优化是本分,优化是情分,有些消极和抵触。


让各个部门吐槽的,还有跟技术部提需求。技术部一直说活多,排不开,响应不了需求。但是,很明显多数人,看起来并不忙,也没有人加班。于是,这几个业务部门领导一碰头,发现都没有开发他们的需求。那他们忙什呢?其实需求提到总监那里,当总监去安排任务时,结果安排不下去,各个组都说自己很忙。最后,总监就向上反馈说自己部门的人都很忙。实际上,可能是几个组长很忙,忙的很烦,不愿接需求,而组员并没有事情做。


整体情况就是这样,老技术们,感觉自己很辛苦,老板也不加钱。不加钱,我没有优化系统的动力,而且你也没有具体的详细策略,出架构那不是我的职责。老板感觉技术部问题频出,系统不稳定,不愿加钱。你干出成绩我才加钱,比如做到今年不宕机,原来需要100万的成本,通过你们技术研发,成本降低到50万。这才叫成绩。


技术:不加钱,我没法努力。老板:干不好,怎么加钱? 两者陷入如此的循环。


老板为了解决技术部的问题,就经常给技术部换领导。因为你告诉老板,宕机的原因是一个接口被调用30多次,他听不懂,也没有解决方案。要钱、要人都好办,你说接口调用太多,他懵了。他只能找一个能对得上话的人去解决。技术部内部是找不出来的,他认为如果存在这样的人,问题就不会发生了。实际上,技术部里的人,都觉着自己能解决,但是前提得加钱。多少钱办多少事,否则我就静止不动,装傻充愣。


结果,就空降了很多领导,换一个不出成果,换一个还是没有起色。但是,每一任领导都会推翻上一位的设计。比如云服务有问题,那我们就自己建机房。下一任领导来了,听说自己的机房不行?我们上云服务不就解决了!这就造成技术部架构经常变,也没有什么积累。更严重的是,员工也倦了,变来变去,反反复复,再有新的改革措施,大家也不愿认真执行了


并且,在这个过程中,业务还是不断积累和发展的。这也堆积了形形色色的病态业务系统。而这些系统,只有老员工能掌握,里面的机关埋伏,根本没有文档,全在他们的脑子里。想改什么东西,复杂不复杂,里面到底怎么个逻辑,老技术说啥就是啥。你想维持生命,又不能让老员工过于动荡,否则会导致业务断层。


倒是也会新来一些空降的技术领导。所有的空降领导,都能发现问题所在。问题大家都知道,实习生都看得出来。 比如缺乏技术领导力,团队没有激励机制,缺乏考核流程,技术债积累严重,技术体系稳定性缺失,业务混乱,人员消极等等。


但新领导也只能做一些表面上的改善。比如,基层管理说员工都不听他的,多次强调要交周报,底下员工就是不交,导致自己不知道他们每周都在干什么。空降领导说,周报写不好,扣工资,看他们交不交。稳定性缺失?把稳定性纳入考核,谁写的代码不稳定,扣工资。说一直忙还不加班?压缩工期,原定10天的任务,让6天干完,这不就忙起来了。 对于系统BUG多,领导说好解决,发现bug,按照数量扣工资,肯定就没有bug了。


实际上这是一种从末端治理的方案,是对洪水的围堵而非疏通。软件系统的配合是复杂的,更需要从源头开始治理。 发现bug扣程序员的工资,属于问题倒推的行为。Bug需要界定是哪方产生的,是单纯代码逻辑问题,还是产品规则问题,还是用户操作方式问题,或者是偶然问题。领导说:那就扣所有参与成员的工资,这样大家都会紧绷一根弦,谁都会为了没有bug而努力。


另外,功能还有复杂和简单之分。一个简单的版本,比如修改个提示语,可能产生不了bug。但是,如果是一项复杂的业务,比如写一个机器人对战,可能会有很多bug。还有,考核是不是应该和职级和工资挂钩?月薪2万的人和月薪5000的,干同一项任务,是不是应该有不同的要求。领导说:有意见?有意见可以去没意见的地方工作。


这又是一个新的轮回,让过于散漫的老技术部,又开始变得剑拔弩张起来。他们将面临新的技术架构,考核体系,工作方式。至于这一轮能给公司带来什么,或许只有时间才能给出答案。


而这个老技术部门的困境,到底能不能走出来,又该如何走出来?



本故事纯属虚构,如有雷同,实属巧合。



作者:TF男孩
来源:juejin.cn/post/7470751370653499427
收起阅读 »

离职转AI独立开发半年,我感受到了真正的生活

离职转AI独立开发半年,我感受到了真正的生活 我的新产品:code.promptate.xyz/ 开场白:一个不被理解的决定 2022年12月的最后一天,我收拾了自己的小盒子,里面装着我在这家互联网公司工作的所有痕迹:一个定制水杯,几本技术书籍,和一摞写满代...
继续阅读 »

离职转AI独立开发半年,我感受到了真正的生活


我的新产品:code.promptate.xyz/


开场白:一个不被理解的决定


photo-1580927752452-89d86da3fa0a.jpeg


2022年12月的最后一天,我收拾了自己的小盒子,里面装着我在这家互联网公司工作的所有痕迹:一个定制水杯,几本技术书籍,和一摞写满代码思路的便利贴。HR部门的小姐姐看着我签完最后一份文件,表情有些复杂:"小张,你才来半年就走,真的想好了吗?这个时候辞职,外面行情不好..."


我点点头,没多解释。如何向别人解释我这个2000年出生的"孩子",毕业仅仅半年就对光鲜的互联网工作心生倦意?如何解释我不想再每天凌晨两点被产品经理的消息惊醒,然后爬起来改几行代码?如何解释我想追求的不只是一份体面的工资和一个看起来不错的头衔?


当我走出公司大楼,北京的冬风刮得我脸生疼。我的储蓄只够支撑我半年,而我计划做的事情——成为一名AI独立开发者——在大多数人眼中无异于天方夜谭。"你疯了吧?现在的独立开发者,有几个能养活自己的?"这是我最好朋友听到我计划时的反应。


事实证明,他错了。我也曾经错了。而现在,当我坐在自己选择的咖啡馆,以自己喜欢的节奏工作,看着用户数突破10,000的后台数据,我知道这半年的挣扎、焦虑和不安都是值得的。


职场困境:我在互联网大厂的日子


回想起入职的第一天,一切都充满希望。校招拿到知名互联网公司的offer,年薪30万,比许多同学高出不少。父母骄傲地向亲戚们宣布他们的儿子"找到了好工作"。


然而现实很快给了我当头一棒。


我被分到一个负责内部工具开发的小组。领导在入职第一天就明确告诉我:"小张,我们这个组不是核心业务,资源有限,但任务不少,你得做好加班的准备。"


第一个月,适应期,我每天工作10小时,感觉还能接受。到了第二个月,一个重要项目启动,我开始习惯每天凌晨回家,第二天早上9点又准时出现在公司。最夸张的一次,我连续工作了38个小时,只为了赶一个莫名其妙被提前的deadline。


# 当时的我就像这段无限循环的代码
while True:
wake_up()
go_to_work()
coding_till_midnight()
get_emergency_task()
sleep(2) # 只睡2小时

工作内容也让我倍感挫折。作为一名热爱技术的程序员,我希望能够参与有挑战性的项目,学习前沿技术。但现实是,我大部分时间都在做重复性的维护工作,修复一些简单但繁琐的bug,或者应对产品经理们不断变化的需求。


我感到自己正在成为一个"代码工具人",一个可以被随时替换的齿轮。我的创造力,我对技术的热情,我想为这个世界带来一些改变的梦想,都在日复一日的996中渐渐磨灭。


转折点:AI浪潮中看到的希望


2022年底,ChatGPT横空出世。作为一个技术爱好者,我第一时间注册了账号,体验了这个令人震惊的产品。我记得那天晚上,我熬夜到凌晨三点,不断地与ChatGPT对话,测试它的能力边界。


"这太不可思议了,"我对自己说,"这将改变一切。"


随后几周,我利用所有空闲时间(其实并不多)研究OpenAI的API文档,尝试构建一些简单的应用。我发现,大语言模型(LLM)并不像我想象的那样遥不可及,即使是一个普通开发者,只要理解其工作原理,也能基于它创造出有价值的产品。


同时,我开始关注独立开发者社区。我惊讶地发现,有不少人依靠自己开发的小产品,实现了不错的收入。虽然他们中的大多数人都经历了长期的积累,但AI技术的爆发似乎提供了一个弯道超车的机会。


这个想法越来越强烈,直到有一天晚上,当我又一次被加到一个紧急项目里,领导发来消息:"小张,这个需求很紧急,今晚能上线吗?"


我望着窗外的夜色,突然感到一阵前所未有的清晰。


我回复道:"可以,这是我在公司的最后一个项目了。"


第二天,我提交了辞职申请。


技术探索:从零开始的AI学习之路


辞职后的第一个月,我给自己制定了严格的学习计划。每天早上6点起床,先锻炼一小时,然后开始我的"AI课程"。


首先,我需要理解大语言模型的基本原理。虽然我有编程基础,但NLP和深度学习对我来说仍是比较陌生的领域。我从《Attention is All You Need》这篇奠定Transformer架构的论文开始,通过各种在线资源,逐步理解了当代大语言模型的工作机制。


# 简化的Transformer注意力机制示例
def scaled_dot_product_attention(query, key, value, mask=):
# 计算注意力权重
matmul_qk = tf.matmul(query, key, transpose_b=True)

# 缩放
depth = tf.cast(tf.shape(key)[-1], tf.float32)
logits = matmul_qk / tf.math.sqrt(depth)

# 添加掩码(可选)
if mask is not :
logits += (mask * -1e9)

# softmax归一化
attention_weights = tf.nn.softmax(logits, axis=-1)

# 应用注意力权重
output = tf.matmul(attention_weights, value)

return output, attention_weights

然后,我需要掌握如何有效地利用OpenAI、Anthropic等公司提供的API。这包括了解Prompt Engineering的技巧,学会如何构建有效的提示词,以及如何处理模型输出的后处理工作。


我还深入研究了向量数据库、检索增强生成(RAG)等技术,这些对于构建基于知识的AI应用至关重要。


Similarity(A,B)=ABA×B=cos(θ)Similarity(A, B) = \frac{A \cdot B}{|A| \times |B|} = \cos(\theta)


这个余弦相似度公式成为了我日常工作的一部分,用于计算文本嵌入向量之间的相似性。


同时,我不断实践、不断失败、不断调整。我记得有一周,我几乎每天睡眠不足5小时,只为解决一个模型幻觉问题。但与公司工作不同的是,这种忙碌源于我的热情和对问题的好奇,而非外部压力。


产品孵化:从创意到实现


学习的同时,我开始思考自己的产品定位。在观察市场和分析自身技能后,我决定开发一款面向内容创作者的AI助手,我将其命名为"创作魔法师"。


这个产品的核心功能是帮助博主、自媒体人和营销人员高效创作内容。与市面上的通用AI不同,它专注于内容创作流程:从选题分析、结构规划、初稿生成到细节优化和SEO改进,提供全流程支持。


产品开发过程中,我遇到了许多挑战:



  1. 技术架构选择:作为独立开发者,资金有限,我需要在功能与成本间找平衡。最终我选择了Next.js + TailwindCSS搭建前端,Node.js构建后端,MongoDB存储数据,Pinecone作为向量数据库存储文档嵌入向量。

  2. 模型优化:为了降低API调用成本,我设计了一套智能路由系统,根据任务复杂度自动选择不同的模型,简单任务用更经济的模型,复杂任务才调用高端模型。

  3. 用户体验设计:没有设计团队,我自学了基础UI/UX知识,参考优秀产品,反复调整界面直到满意。

  4. 运营与推广:这对我这个技术人来说是最大挑战。我学会了编写有吸引力的产品描述,设计落地页,甚至尝试了简单的SEO优化。


最艰难的时刻是产品上线后的第一个月。用户增长缓慢,每天只有个位数的新注册。我开始怀疑自己的决定,甚至一度考虑放弃,重新找工作。


转机:从10个用户到10,000用户


转机出现在上线后的第二个月。一位拥有20万粉丝的自媒体创作者使用了我的产品,对效果非常满意,在他的平台上分享了使用体验。这篇分享在创作者圈内引起了不小的反响。


24小时内,我的注册用户从原来的不到200人猛增至1500多人。服务器一度崩溃,我熬夜进行紧急扩容和优化。这次意外的曝光让我意识到,产品定位是正确的,市场需求确实存在。


接下来,我调整了运营策略:



  1. 主动联系内容创作者,提供免费试用,换取真实反馈和可能的推荐。

  2. 根据用户反馈快速迭代产品功能,每周至少发布一次更新。

  3. 建立用户社区,鼓励用户分享使用技巧,相互帮助。

  4. 编写详细的使用教程和最佳实践指南,降低用户上手难度。


// 用户增长追踪系统的一部分
function trackUserGrowth() {
const date = new Date().toISOString().split('T')[0];

db.collection('metrics').updateOne(
{ date: date },
{
$inc: {
newUsers: 1,
totalImpressions: userSource.impressions || 0
},
$set: {
lastUpdated: new Date()
}
},
{ upsert: true }
);
}

三个月后,用户数突破5,000;半年后,达到10,000。更令人欣慰的是,付费转化率远超我的预期,达到了8%左右,而行业平均水平通常在2-3%。


我分析了成功原因:



  1. 产品聚焦特定痛点:不追求通用性,而是深入解决内容创作者的具体问题。

  2. 及时响应用户需求:独立开发的优势是决策链短,能快速调整方向。

  3. 社区效应:用户之间的口碑传播形成了良性循环。

  4. 个性化服务:我经常亲自回复用户问题,提供定制化建议,这在大公司很难做到。


财务自由:从赤字到收支平衡


谈到收入模式,我采用了"免费+订阅"的策略:



  • 基础功能完全免费,足以满足普通用户的需求

  • 高级功能(如批量处理、高级模板、深度分析等)需要订阅

  • 提供月度计划(49元)和年度计划(398元,约33元/月)


最初几个月,收入微乎其微。我记得第一个月的收入仅有287元,而我在公司的月薪是25,000元。差距之大,让我一度怀疑自己的决定。


但随着用户增长,情况逐渐改善。第三个月收入突破5,000元,第四个月达到12,000元,第六个月——也就是我离职半年后,月收入达到了23,500元,基本与我原来的工资持平。


考虑到我现在的生活成本降低了(不需要租住在北京市中心的高价公寓,不需要每天通勤),实际上我的生活质量反而提高了。


更重要的是,这些收入是真正属于我的,不依赖于任何公司的评价和KPI。我建立了自己的"被动收入引擎",它可以在我睡觉时继续为我工作。


生活平衡:找回被工作吞噬的自我


收入只是故事的一部分。对我来说,最大的变化是生活方式的改变。


在互联网公司工作时,我的生活可以用一句话概括:工作即生活。我几乎没有个人时间,健康状况逐渐恶化,社交圈萎缩到只剩同事,爱好被束之高阁。


成为独立开发者后,我重新掌控了自己的时间:



  • 合理作息:我不再熬夜加班,保持每天7-8小时高质量睡眠。

  • 定期锻炼:每天至少运动一小时,半年下来体重减轻10kg,体脂率降低5%。

  • 地点自由:我可以在家工作,也可以去咖啡馆,甚至尝试了几次"工作旅行",边旅游边维护产品。

  • 深度学习:不再为了应付工作而学习,而是追随个人兴趣深入研究技术。

  • 重拾爱好:我重新开始弹吉他,参加了当地的音乐小组,结识了一群志同道合的朋友。


这种生活方式让我找回了工作的意义——工作是为了更好的生活,而不是生活为了工作。我的创造力和工作热情反而因此提升,产品迭代速度和质量都超出了预期。


技术反思:AI时代的个人定位


在这半年的独立开发经历中,我对AI技术和个人发展有了更深的思考。


首先,大模型时代确实改变了软件开发的范式。传统开发模式是"写代码解决问题",而现在更多的是"设计提示词引导AI解决问题"。这不意味着编程技能不重要,而是编程与AI引导能力的结合变得越来越重要。


# 传统开发方式
def analyze_sentiment(text):
# 复杂的NLP算法实现
words = tokenize(text)
scores = calculate_sentiment_scores(words)
return determine_overall_sentiment(scores)

# AI时代的开发方式
def analyze_sentiment_with_llm(text):
prompt = f"""
分析以下文本的情感倾向,返回'正面'、'负面'或'中性'。
只返回分类结果,不要解释。
文本: {text}
"""

result = llm_client.generate(prompt, max_tokens=10)
return result.strip()

其次,我认识到技术民主化的力量。曾经需要一个团队才能完成的项目,现在一个人借助AI工具也能完成。这为独立开发者创造了前所未有的机会,但也意味着差异化和创新变得更加重要。


最后,我发现真正的核心竞争力不在于熟悉某项技术,而在于解决问题的思维方式和对用户需求的理解。技术工具会不断更新迭代,但洞察问题和设计解决方案的能力将长期有效。


写给迷茫的年轻人


回顾这半年的经历,我想对那些和当初的我一样迷茫的年轻人说几句话:



  1. 公司经历有价值,但不是唯一路径:在大公司工作能积累经验和人脉,但不要把它视为唯一选择。如果环境压抑了你的创造力和热情,寻找改变是勇敢而非逃避。

  2. 技术浪潮创造机会窗口:AI等新技术正在重构行业,为个人提供了"弯道超车"的机会。保持开放心态,持续学习,你会发现比想象中更多的可能性。

  3. 找到可持续的节奏:成功不在于短期的爆发,而在于长期的坚持。设计一种既能推动目标实现又不会消耗自己的工作方式,才能走得更远。

  4. 用户价值胜过技术炫耀:最成功的产品往往不是技术最先进的,而是最能解决用户痛点的。专注于创造真正的价值,而不仅仅是展示技术能力。

  5. 享受过程,而非仅追求结果:如果你只关注最终目标而忽视日常体验,即使达到目标也可能感到空虚。真正的成功包含了对过程的享受和个人成长。


未来展望:持续进化的旅程


现在,我站在新的起点上。"创作魔法师"只是我旅程的第一步,我已经开始规划下一个产品,瞄准了另一个我认为有潜力的细分市场。


与此同时,我也在考虑如何扩大团队规模。虽然独立开发有其魅力,但有些想法需要更多元的技能组合才能实现。我计划在未来半年内招募1-2名志同道合的伙伴,组建一个小而精的团队。


技术上,我将继续深入研究大模型的微调和部署技术。随着开源模型的进步,在特定领域微调自己的模型变得越来越可行,这将是我产品的下一个竞争优势。


生活方面,我正计划一次为期两个月的"数字游牧"之旅,边旅行边工作,探索更多可能的生活方式。


路上会有挑战,也会有挫折,但我不再惧怕。因为我知道,真正的自由不在于没有困难,而在于面对困难时仍能按自己的意愿选择前进的方向。


当我在咖啡馆工作到黄昏,看着窗外的夕阳,我常常感到一种难以言喻的满足感。这种感觉告诉我,我正在正确的道路上——一条通往真正生活的道路。


如果你也在考虑类似的选择,希望我的故事能给你一些启发。记住,每个人的路都不同,重要的是找到属于自己的节奏和方向。


在这个AI加速发展的时代,机会前所未有,但终究,技术只是工具,生活才是目的。


作者:aircrushin
来源:juejin.cn/post/7486788421932400652
收起阅读 »

好人难当,坏人不做

好人难当,以后要多注意了,涨点记性。记录三件事情证明下: 1. 免费劳动 之前和一个同学一起做一个项目,说是创业,不过项目做好了,倒是他家店铺自己用起来了,后来一直让我根据他家的需求进行修改,我也一一的改了,他倒是挺感谢我的,说是请吃饭。不过也一直没请,后面都...
继续阅读 »

好人难当,以后要多注意了,涨点记性。记录三件事情证明下:


1. 免费劳动


之前和一个同学一起做一个项目,说是创业,不过项目做好了,倒是他家店铺自己用起来了,后来一直让我根据他家的需求进行修改,我也一一的改了,他倒是挺感谢我的,说是请吃饭。不过也一直没请,后面都一年多过去了,还让我免费帮他改需求,我就说没时间,他说没时间的话可以把源码给他,他自己学着修改,我就直接把源码给他了,这个项目辛苦了一个多月,钱一毛也没赚到,我倒是搭进去一台服务器,一年花了三百多吧。现在源码给他就给他了吧,毕竟同学一场。没想到又过了半年,前段时间又找我来改需求了。这个项目他们家自己拿着赚钱,又不给我一毛钱,我相当于免费给他家做了个软件,还要出服务器钱,还要免费进行维护。我的时间是真不值钱啊,真成义务劳动了。我拒绝了,理由是忙,没时间。


总结一下,这些人总会觉得别人帮自己是理所当然的,各种得寸进尺。


2. 帮到底吧


因为我进行了仲裁,有了经验,然后被一个人加了好友,是一个前同事(就是我仲裁的那家公司),然后这哥们各种问题我都尽心回答,本着能帮别人一点就帮别人一点的想法,但是我免费帮他,他仲裁到手多少钱,又不会给我一毛钱。这哥们一个问题接一个,我都做了回答,后来直接要求用我当做和公司谈判的筹码,我严词拒绝了,真不知道这人咋想的,我帮你并没有获得任何好处,你这个要求有点过分了,很简单,他直接把我搬出来和公司谈判,公司肯定会找我,会给我带来麻烦,这人一点也没想这些事。所以之后他再询问有关任何我的经验,我已经不愿意帮他了。


总结一下,这些人更进一步,甚至想利用下帮自己的人,不考虑会给别人带来哪些困扰。


3. 拿你顶缸


最近做了通过一个亲戚接了一个项目,而这个亲戚的表姐是该项目公司的领导,本来觉得都是有亲戚关系的,项目价格之类开始问了,他们没说,只是说根据每个人的工时进行估价,后面我们每个人提交了个人报价,然后还是一直没给明确答复,本着是亲戚的关系,觉得肯定不会坑我。就一直做下去了,直到快做完了,价格还是没有出来,我就直接问了这个价格的事情,第二天,价格出来了,在我报价基础上直接砍半。我当然不愿意了,后来经过各种谈判,我终于要到了一个勉强可以的价格,期间群里谈判也是我一个人在说话,团队的其他人都不说话。后来前端的那人问我价格,我也把过程都实话说了,这哥们也要加价,然后就各种问我,我也啥都告他了。后来这个前端在那个公司领导(亲戚表姐)主动亮明身份,她知道这个前端和那个亲戚关系好,然后这个前端立马不好意思加价了,并且还把锅甩我头上,说是我没有告诉他她是他姐。还说我不地道,我靠,你自己要加价,关我啥事,你加钱也没说要分我啊,另外我给自己加价的时候你也没帮忙说话啊,我告诉你我加价成功了是我好心,也是想着你能加点就加点吧,这时候你为了面子不加了,然后说成要加价的理由是因为我,真是没良心啊。后面还问我关于合同的事情,我已经不愿意回答他了,让他自己找对面公司问去。


总结一下,这些人你帮他了他当时倒是很感谢你,但是一旦结果有变,会直接怪罪到你头上。


4. 附录文章


这个文章说得挺好的《你的善良,要有锋芒》


你有没有发现,善良的人,心都很软,他们不好意思拒绝别人,哪怕为难了自己,也要想办法帮助身边的人。善良的人,心都很细,他们总是照顾着别人的情绪,明明受委屈的是自己,却第一时间想着别人会不会难过。


也许是习惯了对别人好,你常常会忽略自己的感受。有时候你知道别人是想占你便宜,你也知道别人不是真心把你当朋友,他们只是觉得你好说话,只是看中了你的善良,但是你没有戳穿,你还是能帮就帮,没有太多怨言。


你说你不想得罪人,你说你害怕被孤立,可是有人在乎过你吗?


这个世界上形形色色的人很多,有人喜欢你,有人讨厌你,你没有办法做到对每一个人好,也没办法要求每一个人都是真心爱你。所以你要有自己的选择,与舒服的人相处,对讨厌的人远离,过你自己觉得开心自在的生活就好,没必要为了便利别人,让自己受尽委屈。


看过一段话:善良是很珍贵的,但善良要是没有长出牙齿来,那就是软弱。


你的善良,要有锋芒,不要把时间浪费在不值得的人身上。对爱你的人,倾心相助,对利用你的人,勇敢说不。


愿你的善良,能被真心的人温柔以待。


作者:一线大码
来源:juejin.cn/post/7455667125798780980
收起阅读 »

如何优雅的回复面试官问:“你能接受加班吗?”

面试官问:“你能接受加班吗?”我脑袋嗡的一声,余音绕梁三日不绝于耳。 那一刻,我简直觉得自己像被突然砸中脑袋,脑袋里嗡的一声,余音绕梁三日。作为一个职场小白,这种问题简直颠覆了我对面试的认知。于是,我一时心血来潮,脱口而出一句:“领导抗揍吗?” 结果,大家猜到...
继续阅读 »

面试官问:“你能接受加班吗?”我脑袋嗡的一声,余音绕梁三日不绝于耳。


那一刻,我简直觉得自己像被突然砸中脑袋,脑袋里嗡的一声,余音绕梁三日。作为一个职场小白,这种问题简直颠覆了我对面试的认知。于是,我一时心血来潮,脱口而出一句:“领导抗揍吗?” 结果,大家猜到了,面试是上午结束的,Offer是当天中午凉的。


是牛是马


如何巧妙回答


“我认为加班是工作中不可避免的一部分,尤其是在一些特殊项目或紧急情况下。我非常热爱我的工作,并且对公司的发展充满信心,因此我愿意为了团队的成功付出额外的努力。当然,我也注重工作效率和时间管理,尽量在正常工作时间内完成任务。如果确实需要加班,我也会根据公司合理的安排,积极的响应。”


作为一名资深的面试官,今天面对这个问题,坐下来和大家聊聊应该怎么回答呢?面试官究竟喜欢怎样的回答?让我们深入分析一下。


面试官的心理


在职场中,想要出色地应对面试,需要具备敏锐的观察力和理解力。学会细致入微地观察,善于捕捉每一个细微的线索,这样才能在面试中游刃有余。懂的察言观色,方能尽显英雄本色。


请在此添加图片描述


面试官的考量点



  • 评估工作稳定性


面试官提出“能否接受加班”的问题,旨在深入了解求职者的职业稳定性和对加班安排的适应性。这一评估有助于预测求职者入职后的表现和长期留任的可能性。工作稳定性是企业考量员工的关键指标之一,通过这一问题,面试官能够洞察求职者的职业发展规划及其对未来工作的期望。



  • 筛选合适的候选人


通过询问加班的接受度,面试官筛选出那些愿意为达成工作目标而投入额外时间和精力的候选人。这种筛选方式有助于确保团队的整体运作效率和协作精神。合适的候选人不仅能快速融入团队,还能显著提升工作效率。因此,面试官借此问题寻找最匹配岗位需求的员工。



  • 了解求职者的价值观


面试官还利用这个问题来探查求职者的价值观和工作态度,以此判断他们是否与公司的文化和核心价值观相契合。员工的价值观和态度对公司的长远发展起着至关重要的作用。通过这一询问,面试官能够确保求职者的个人目标与公司的发展方向保持一致,从而促进整体的和谐与进步。


考察的问题的意义


要理解问题的本质……为什么面试官会提出这样的问题?难道是因为你的颜值过高,引发了他的嫉妒?


请在此添加图片描述



  • 工作态度


面试官通过询问加班的接受度,旨在评估求职者是否展现出积极的工作态度和强烈的责任心。在许多行业中,加班已成为常态,面试官借此问题了解求职者是否愿意在工作上投入额外的时间和精力。积极的工作态度和责任心是职场成功的关键因素,通过这一问题,面试官能够初步判断求职者是否适应高强度的工作环境。



  • 岗位匹配度


特定岗位因其工作性质可能需要频繁加班。面试官通过提出加班相关的问题,旨在了解求职者是否能适应这类岗位的工作强度。由于不同岗位对工作强度的要求各异,面试官希望通过这一问题确保求职者对即将承担的角色有明确的认识,从而防止入职后出现期望不一致的情况。



  • 抗压能力


加班往往伴随压力,面试官通过这一问题考察求职者的抗压能力和情绪管理技巧。抗压能力对于职场成功至关重要,面试官借此了解求职者在高压环境下的表现,以判断其是否符合公司的需求。



  • 公司文化


面试官还利用这个问题来评估求职者对公司加班文化的接受程度,以此判断其价值观是否与公司相符。公司文化对员工的工作体验和满意度有着深远的影响,面试官希望通过这一问题确保求职者能够认同并融入公司文化。


回答的艺术


“知己知彼,百战不殆。”在面试中,回答问题的关键在于展现出积极和正向的态度。


请在此添加图片描述



  • 积极态度


在回答有关加班的问题时,表达你对工作的热爱和对公司的忠诚,强调你愿意为了团队的成功而付出额外的努力。这种积极的态度不仅展示了你的职业素养和对工作的热情,还能显著提升面试官对你的好感。


例如:“我非常热爱我的工作,并且对公司的发展充满信心。我相信为了实现公司的目标和团队的成功,适当的加班是可以接受的。”



  • 灵活性和效率


强调你在时间管理和工作效率上的能力,表明你在确保工作质量的同时,会尽可能减少加班的需求。灵活性和效率是职场中极为重要的技能,面试官可以通过这个问题了解你的实际工作表现。


例如:“我在工作中注重效率和时间管理,通常能够在规定的工作时间内完成任务。当然,如果有特殊情况需要加班,我也会全力以赴。”



  • 平衡工作与生活


适当地提到你对工作与生活平衡的重视,并希望公司在安排加班时能够充分考虑到员工的个人需求。平衡工作与生活是职场人士普遍关注的问题,面试官通过这个问题可以了解你的个人需求和期望。


例如:“我非常重视工作与生活的平衡,希望在保证工作效率的同时,也能有足够的时间陪伴家人和进行个人活动。如果公司能够合理安排加班时间,我会非常乐意配合。”



  • 适度反问


在回答时,可以适当地向面试官询问关于公司加班的具体情况,以便更全面地了解公司的加班文化和预期。这样的反问可以展现你的主动性和对公司的兴趣,有助于获取更多信息,做出更加明智的回答。


例如:“请问公司通常的加班情况是怎样的?是否有相关的加班补偿或调休安排?”


最后


所谓士为知己者死,遇良将则冲锋陷阵,择良人则共谋天下。在职场这场没有硝烟的战争中,我们每个人都是一名战士,寻找着属于自己的知己和良将。当面试官提出挑战性问题时,我们不仅要展示自己的能力和才华,更要表现出对工作的热爱和对公司的忠诚。


面对“你能接受加班吗?”这样的问题,我们应以积极的态度、灵活的思维和对工作与生活平衡的重视来回应。这样的回答不仅能展示我们的职业素养,还能让我们在众多求职者中脱颖而出,赢得面试官的青睐。


正如士为知己者死,我们在职场中也要找到那个能理解我们、支持我们的知己;遇良将则冲锋陷阵,我们要在优秀的领导下发挥自己的潜能,为公司的发展贡献力量;择良人则共谋天下,我们要与志同道合的同事共同努力,实现职业生涯的辉煌。


总之一句话,在面试中展现出积极向上的形象,不仅能为我们的职业生涯加分,更能让我们在职场上找到属于自己的价值和归属感。让我们以这句话为指引,勇敢地迎接职场的挑战,书写属于自己的辉煌篇章。


作者:不惑_
来源:juejin.cn/post/7457211584709066792
收起阅读 »

工作7年了,才明白技术的本质不过是工具而已,那么未来的方向在哪里?

前言 Hi 你好,我是东东拿铁,一个正在探索个人IP&副业的后端程序员。 五一过去了,不知道大家有没有好好的放松自己呢?愉快的假期总是这么短暂,打工人重新回到自己的岗位。 我目前工作7年了,这几年来埋头苦干,学习了很多技术,做了不少系统,也解决过不少线...
继续阅读 »

前言


Hi 你好,我是东东拿铁,一个正在探索个人IP&副业的后端程序员。


五一过去了,不知道大家有没有好好的放松自己呢?愉快的假期总是这么短暂,打工人重新回到自己的岗位。


我目前工作7年了,这几年来埋头苦干,学习了很多技术,做了不少系统,也解决过不少线上问题。自己虽然在探寻个人IP与副业,自己花了很多时间去思考技术之外的路该怎么走。但转念一想,我宁愿花这么多时间去探索技术之外的路线,但是却从没好好静下来想一下技术本身。


技术到底是什么,你我所处的技术行业为什么会存在,未来的机会在哪里。


因此,我结合自己的工作经历,希望和大家一起聊聊,技术的本质与未来的方向,到底在哪里,才疏学浅,如果内容有误还希望你在评论区指正。


背景


行业现状


互联网行业发展放缓,进入调整阶段,具体表现为市场需求、用户规模、营收利润、创新活力等方面的放缓或下降。


一些曾经风光无限的互联网公司也遭遇了业绩下滑、股价暴跌、裁员潮等困境,你是不是也曾听过互联网的寒冬已至的言论?


其实互联网本身,并没有衰败或消亡,而是因为互联网高速发展的时代过去了。



  1. 中国经济增速放缓、消费升级趋势减弱、人口红利消失等因素的影响,中国互联网市场的需求增长趋于饱和或下降。

  2. 用户规模停滞,智能手机普及率饱和,互联网用户规模增长趋于停滞,由增量市场变为存量市场,互联网获客成本越来越高。

  3. 监管政策收紧,互联网行业规范和监管愈加严格,更加注重合规,因此互联网行业也会收到影响。


供需环境


供需环境变化,应届生要求越来越高,更加注重学历。


社招更是看中学历的同时,开始限制年龄。招聘更看重项目经验,业务经验。五年前,你只要做过一些项目,哪怕不是实际使用的,也很容易拿到offer。而现在企业在看中技术能力的同时,还会关注候选人对与行业的理解,以及以往的工作经验。


技术的本质


先说结论,技术的本质是工具。 我把过去几年的认知变化分成了四个阶段,给大家展示一下我对于技术的认知成长过程。


第一阶段


技术就是应用各类前沿的框架、中间件。


刚毕业时,我就职于一家传统信息企业。谈不上所谓的架构,只需要Spring、Mysql就构建起了我们的所有技术栈。当然,微服务框架更不可能,Redis、MQ在系统中都没使用到。


此时互联网企业已经开始快速发展,抖音诞生区区不过一年。


一线城市的互联网公司,都已经开始使用上了SpringBoot、微服务,还有各类我没有听说过的中间件。


工作环境的闭塞,让我对各类技术有着无限憧憬,因为很多当下难以解决的问题,应用一些新技术、新架构,就能立刻对很多难题降维打击。


举个例子,如果你使用本地缓存,那么集群部署时,你一定要考虑集群的缓存一致性问题,可这个问题如果用上分布式缓存Redis,那么一致性问题迎刃而解。


所以那个时候的我认为,技术就是应用各类中间件,只要用上这些中间件、框架,我就已经走在了技术的前沿。


第二阶段


技术对我而言就是互联网。
半年后,我摆脱传统行业,来到了一个小型互联网公司,用上了不少在我眼中的新技术。


但任何新技术,如果只停留在表面,那么对于使用者来说,就是几个API,几行代码,你很快就会感到厌倦,发现问题也会焦虑,因为不清楚原理,问题就无从排查。


很快,所谓的“新技术”,就不能给我带来成就感了。我开始羡慕那些互联网行业APP,无时无刻都在畅想着,如果我做的产品能够被大家看到并应用,那该是多么有意思的一件事情。


于是我又认为,技术就是做那些被人看见、被人应用的网站、APP。


第三阶段


技术就是高并发、大流量、大数据。
当自己真正负责了某一个APP的后端研发后,很多技术都有机会应用,也能够在AppStore下载自己的APP了,没事刷一刷,看到某一个信息是通过我自己写的代码展示出去,又满足了第二阶段的目标了。


那么我接下来追求的变成了,让更多的人使用我做的产品,起码让我的亲人、朋友也能看到我做的东西。


当然,随之而来的就是日益增长的数据规模和大流量,这些无时无刻都在挑战系统的性能,如何去解决这些问题,成为了我很长一段时间的工作主线。


应对高并发、大流量,我们需要对系统作出各种极致性能的优化。


为了性能优化,还需要了解更多的底层原理,才能在遇到问题时有一个合理的解决方案。


所以,我认为技术就是高并发、大数据,做好这些,才算做好了技术。


第四阶段


经过了传统企业,到互联网公司,再到互联网大厂的一番经历,让我发现技术的本质就是工具,在不同阶段,去解决不同的问题。


在第一阶段,技术解决了各类行业的数据信息化问题,借助各类中间件、架构把具体的需求落地。


在第二阶段、第三阶段,技术解决了业务的规模化问题,因为在互联网,流量迅猛增长,我需要去用技术解决规模化带来的各类的问题,做出性能优化。


当然,技术在其他领域也发挥着作用,比如AI&算法,给予了互联网工具“智能化”的可能,还有比如我们很难接触到的底层框架研发,也就是技术的“技术”,这些底层能力,帮助我们更好的发挥我们的技术能力。


未来机会


大厂仍是最好的选择


即使是在互联网增速放缓、内卷持续严重的今天,即使我选择从大厂离职,但我依然认为大厂是最好的选择。


为什么这么说,几个理由



  • 大厂有着更前沿的技术能力,你可以随意选择最适合的工具去解决问题

  • 大厂有着更大的数据、流量规模,你所做的工作,天然的就具备规模化的能力

  • 大厂有先进的管理方法,你所接触的做事方法、目标管理可能让你疲倦,但工作方法大概率是行业内经过验证的,你不会走弯路,能让你有更快的进步速度


数字化转型


如果你在互联网行业,可能没有听说过这个词,因为在高速发展的互联网行业,本身就是数字驱动的,比如重视数据指标、AB实验等。但在二线、三线城市的计算机行业或者一些传统行业,数字化转型是很大的发展机会。


过去十年,传统行业做的普遍是信息化转型,也就是把线下,需要用纸、笔来完成工作的,转移到系统中。


那什么是数字化转型?



我用我自己的理解说一下,数字化转型就是业务流程精细化管理,数据驱动,实现降本增效。



我目前所在的公司的推进大方向之一,就是数字化转型。因为许多行业的数字化程度非常低,本质而言,就是把数字驱动的能力,带给传统企业,让传统企业也能感受到数字化带来的发展可能。


举个例子,比如一个餐饮系统数字化转型后,一方面可以把用户下单、餐厅接单、开始制作、出餐、上餐线上化,还可以和原材料供应系统打通,当有订单来时,自动检测餐饮的库存信息,库存不足及时提供预警,甚至可以作出订单预测,比如什么时间点,哪类餐品的点单量最高。


当然,数字化转型与互联网有着极大的不同,在互联网行业,你只需要坐在工位,等着产品提出需求就可以了。但是传统行业,你需要深入客户现场,实地查看业务流程,与用户交谈,才能真正的理解客户需求。


或许这样的工作并不炫酷,还需要出差,但在互联网行业饱和的今天,用技术去解决真实世界的问题,也不失为一个很好的选择。


AI&智能化


随着AI快速发展,各类智能化功能已经遍布了我们使用的各类APP,极客时间有了AI自动总结,懂车帝有了智能选车度搜索问题,有时候第一个也会是AI来给我们解答。



任何行业遇上AI都可以再做一遍。



抛开底层算法、模型不谈,但从使用者角度来说,最重要的是如何与行业、场景结合相使用。但是想要做好应用,需要你在行业有着比较深的沉淀,有较深的行业认知。


当然,智能化也不仅限于AI,像上面餐饮系统的例子,如果能够实现订单预测、自动库存管理,其实也是智能化的体现。


终身学习


技术能力


持续精进专业技术能力,相信大家对此都没有疑问。


对于日常使用到的技术,我们需要熟练掌握技术原理,积累使用经验,尤其是线上环境的问题处理经验。


第一个是基础。比如对集合类,并发包,IO/NIO,JVM,内存模型,泛型,异常,反射,等有深入了解,最好是看过源码了解底层的设计。


第二你需要有全面的互联网技术相关知识。从底层说起,你起码得深入了解mysql,redis,nginx,tomcat,rpc,jms等方面的知识。


第三就是编程能力,编程思想,算法能力,架构能力。


在这个过程中,打造自己的技能树,构建自己的技术体系。


对于不断冒出的新技术,我们一方面要了解清楚技术原理,也要了解新技术是为了解决什么问题,诞生于什么背景。


业务能力


前面说到技术是一种工具,解决的是现实世界的问题,如果我们希望更好的发挥技术的作用,那么就需要我们先掌握好业务领域。


互联网领域
如果你想要快速地入门互联网领域的业务,你可以使用AARRR漏斗模型来分析。


AARRR这5个字母分别代表 Acquisition、Activation、Retention、Revenue 和 Refer
五个英文单词,它们分别对应用户生命周期中的 5 个重要环节:获取(Acquisition)、激活(Activation)、留存(Retention)、收益(Revenue)和推荐(Refer)。


AARRR 模型的核心就是以用户为中心,以完整的用户生命周期为指导思想,分析用户在各个环节的行为和数据,以此来发现用户需求以及产品需要改进的地方。


举一个简单的例子,我们以一个互联网手游 LOL来举例:
获取就是用户通过广告、push等形式,了解到了游戏并注册或者登陆。
激活就是用户真正的开始游戏,比如开始了一场匹配。
留存就是用户在7天、30天内,登陆了几次,打了几把比赛,几天登陆一次,每日游戏时常又是多少。
收益,用户购买皮肤了,产生了收益。
推荐,用户邀请朋友,发送到微信群中,邀请了朋友一起开黑。


如果你所在的行业是C端产品,那么这个模型基本可以概括用户的生命周期全流程。


传统行业
传统行业没有比较通用的业务模型,如果想要入手,需要我们从以下三个角度去入手



  1. 这个行业的商业模式是什么,也就是靠什么赚钱的?比如售卖系统收费,收取服务费等

  2. 行业的规模如何?头部玩家有哪些?它们的模式有哪些特色?

  3. 这个行业的客户是谁、用户是谁?有哪些经典的作业场景?业务操作流程是什么样的?


如何获取到这些信息呢?有几种常见的形式



  1. 权威的行业研究报告,这个比较常见

  2. 直接关注头部玩家的官网、公众号、官媒

  3. 深入用户现场


我们以汽车行业来举例
商业模式:整车销售、二手车、汽车租赁等,细分一点,又有传统动力和新能源两种分类。
规模:如下图


头部车企:传统的四大车企一汽、东风、上汽、长安,新势力 特斯拉、蔚小理


经典场景:直接去4S店体验一下汽车销售模式、流程


说在最后


好了,文章到这里就要结束啦,我用我自己工作几年的不同阶段,给你介绍了我对于技术的本质是工具的思考过程,也浅浅的探寻了一下,未来的发展机会在哪里,以及我们应该如何提升自己,很感谢你能看到最后,希望对你有所帮助。


不知道你对于技术是怎么看的,又如何看待当下的市场环境呢?欢迎你在评论区和我分享,也希望你点赞、评论、收藏,让我知道对你有所收获,这对我来说很重要。也欢迎你加我的wx:Ldhrlhy10,一起交流。


本篇文章是第33篇原创文章,2024目标进度33/100,欢迎有趣的你关注我~


作者:东东拿铁
来源:juejin.cn/post/7365679089812553769
收起阅读 »

我在团队内部提倡禁用单元测试

先说结论: 在绝大部分的业务前端开发中,写单元测试的收益非常小,但是带来的维护成本却非常大,请不要再写单元测试感动自己,为难同事了。 现在很多单元测试的教程都是那种很简单的比如,测个 1+1=2,这需要测吗?下面这段代码已经出现过很多次了,纯纯的误导人。 co...
继续阅读 »

先说结论:
在绝大部分的业务前端开发中,写单元测试的收益非常小,但是带来的维护成本却非常大,请不要再写单元测试感动自己,为难同事了。


现在很多单元测试的教程都是那种很简单的比如,测个 1+1=2,这需要测吗?下面这段代码已经出现过很多次了,纯纯的误导人。


const sum = (a,b) => a+b
it('1+1=2',()=> {
expect(sum(1,1)).toBe(2)
})

稍微上点复杂度,来写个组件的单测,比如一个用户信息展示组件,叫 UserInfoBlock,支持设置头像的大小,点击名字支持跳转到个人主页,组件代码大致长这样


interface UserInfoBlockProps {
name: string
size: 16 | 24
id: string
icon: string
}
export const UserInfoBlock:FC<UserInfoBlockProps> = (props) => {
const navigate = useNavigate()
return <div
class='xxxxxx'
style={{width: props.size}}
onClick={() =>
{navigate(`/user/${props.id}`)}}>
<img src={props.icon}/>
{props.name}
</div>

}

然后开始给组件写单测,先测头像大小的功能


import { UserInfoBlock, UserInfoBlockProps } from './user-info-block'
import { fireEvent, render, screen } from '@testing-library/react'
describe('UserInfoBlock 组件单测', () => {
const userInfo:UserInfoBlockProps = {
name: '张三',
icon:'https://xxx.png',
id:'abcd1234',
size: 16
}
const userInfoLarge:UserInfoBlockProps = {
name: '张三',
icon:'https://xxx.png',
id:'abcd1234',
size: 24
}
describe('展示默认头像大小', () => {
const component = render(<UserInfoBlock {...userInfo}/>)
it('img 标签的宽度为 16px', () => {
expect(screen.getByTag('img').style.width).toBe(16)
})
})
describe('展示large头像大小', () => {
const component = render(<UserInfoBlock {...userInfoLarge}/>)
it('img 标签的宽度为 24px', () => {
expect(screen.getByTag('img').style.width).toBe(24)
})
})
})


接下来测一下跳转,因为用了 react-router,所以在渲染组件的时候必须包裹一下 RouterProvider


...
describe('点击可以跳转', () => {
const component = render(<MemoryRouter>
<UserInfoBlock {...userInfoLarge}/>
</MemoryRouter>

)
fireEvent.click(component.div)
it('url 会变成 user/abcd1234', () => {
expect(location.pathname).toBe('user/abcd1234')
})
})
...

这个组件的测试就写完了,看起来挺有用,但实际没啥用。


首先这个测试的收益不高,因为这是一个很简单的组件,五分钟写完,但是写这个测试需要翻倍的时间,因为需要构造数据,之前没有经验不知道要加 MemoryRouterjestlocation 对象不方便,还要 mock 一下。等把这一套搞完了才能跑通,这就好像你疯狂锻炼,练出麒麟臂,就是为了举自拍杆举的稳一点。如果组件内要发请求,要做的准备工作就更加多了。


其次,user/abcd1234是什么,断言这个没用,因为别人改了链接,你的测试也一样会过,应该断言成功的打开了用户主页,比如断言一个必定会存在的文字expect(screen.getByText('用户详情')).toBeInDocument()这才能证明真的打开了用户主页。


1+1 什么时候不等于 2。头像设置 16px,什么时候不会是 16 px。什么时候点击不跳转到用户主页。肯定是有人修改了这里的业务逻辑才会这样,只有在做产品需求,代码优化的时候才会去改以前的代码。那么这时,这段测试对接手这段代码的人就是负担。


假设我接到需求,用户主页url 变了,改成 user?id=xxx。我心想这个简单,一秒钟解决,提了 pr 发现测试挂了,然后我就得把测试也改一下。


如果一段测试代码在我每次修改需求的时候都要改,甚至有的时候还会为了便于测试在业务代码中留一些后门,那这个测试就是纯纯的副作用。


大家肯定深有体会,一般一个模块自己不会出问题,但是多个模块组合起来就很容易出问题了,所以测试的重点不应该是一个组件内部各种细节,而应该测这个组件在被使用的地方是否正确。


举个例子,比如在一个列表里面,使用头像为 24px 的用户组件,然后有一天出 bug 了,说这里变成 16 了。那这会是组件的 bug 吗,这肯定是使用的地方没有用对。所以应该要测试的是这里。如果有个测试断言了在列表中用户头像必须为 24px,即使没有组件的单测,这个组件也不会被改坏,因为上层已经覆盖到了。


什么是好的测试?



  1. 我认为好的测试是稳定的测试,不仅不需要经常修改,甚至还能扛住代码重构。比如你把项目从 react 完全迁移到了 vue,测试都能跑过。

  2. 好的测试是可以当作项目文档的,组内来新人了,不需要给他介绍过多,有问题让他自己看测试用例就能理解业务。


那么怎么写出这样的测试呢?答案就是写集成测试,集成测试说白了就是一个超级大的单测,之前测试 render 的是一个组件,现在直接 render(<App/>),将路由跳转,请求 mock,fake数据库等等都统一处理。可以将上面写的测试简单的改为


import { creatAppContext, AppContext } from './app-test-context'
describe('S: 测试头像组件', () => {
let _:AppContext
beforeEach(() => {
- = creatAppContext()
})
describe('W: 去用户列表也', () => {
beforeEach(() => {
_.click(screen.getByText('查看用户列表'))
})
it('T: 列表页有十个用户,用户头像是 24px', ()=>{
expect(screen.getAllByTestid('user-item').length).toBe(10)
expect(screen.getAllByTestid('user-item')[0].img.style.width).toBe(24)
})
describe('W: 点击第一个用户', () => {
beforeEach(() => {
_.click(screen.getAllByTestid('user-item')[0])
})
it('T: 打开了用户主页', () => {
expect(screen.getByText('用户详情')).toBeInDocument()
})
})
})
})

关于怎么写好测试可以展开的点实在太多了,就不过多阐述,想要了解的朋友可以查看我的主页,之前专门出过一些列文章详细的讲这些事情。


作者:阿古达木
来源:juejin.cn/post/7478515057510154255
收起阅读 »

8年程序员本以为到头了,没想到柳暗花明...

讲一个这两年发生在我身上的故事,一个从程序员到AI产品负责人,一个选择大于努力的故事: 回到2022年,作为一个8年的前端程序员的我,在一家行业头部的企业中勤勤恳恳,兢兢业业。每天与代码为伴,沉浸在React的世界里,整日优化、升级、写框架、写工具,解决点疑难...
继续阅读 »

讲一个这两年发生在我身上的故事,一个从程序员到AI产品负责人,一个选择大于努力的故事:


回到2022年,作为一个8年的前端程序员的我,在一家行业头部的企业中勤勤恳恳,兢兢业业。每天与代码为伴,沉浸在React的世界里,整日优化、升级、写框架、写工具,解决点疑难杂症,改改BUG,后来甚至成为了React的contributor。


我的生活和工作都很稳定,技术能力也得到了领导和团队的认可。


但内心深处却隐隐感到一种不安——前端技术的发展似乎进入了瓶颈期,我的职业生涯也仿佛停滞不前。


随着时间的推移,我开始面临两个无法回避的问题:



  1. 个人能力无法进一步提升:前端技术的更新速度放缓,框架和工具趋于成熟,我能做的事情越来越少了。

  2. 薪资增长停滞:薪资似乎已经到达了行业的天花板,如果我不能做更多的事情,也再难有突破。


自己是否已经走到了职业生涯的尽头?


面对这个问题,我一度陷入迷茫。跟其他程序员一样,我也尝试学习新的技术栈来缓解心中的这份焦虑,更底层的语言比如Rust、更宽的技术栈比如three.js、学学区块链、学学算法。


shu3.jpg
但是随之而来的就是,这些东西我学了之后除了做做demo、写写小工具之外,我好像做不了什么大事,我没有动力向着更深的内容走下去,这反而更加加深了我的焦虑。


那时候我32岁,每天都在担心中年危机。担心三年之后我凭什么和体力更好的、钱更少的、拥有同样技术栈的年轻人竞争?【虽然三年后的今天,并没有这样的年轻人出现】


幸运的是,2022年年底,chatGPT爆火全球。一夜之间,所有人都在讨论GPT,我也不例外,按照惯例,我再次把学习AI加入了我的日程。


当时体验了chatGPT之后,我两眼放光,我觉得,只要我努力学习这个技术,我一定可以像当初选择前端开发一样,再次进入一个程序员的风口,于是报课、买书、找行业大佬交流。


就这样过来两三个月......


你以为怎么了?我柳暗花明了? 这是一个前端程序员逆袭转战AI年薪百万的故事? 很不幸,这并不是。


事实是三个月之后,我再次陷入了困境:AI的底层技术,一我根本学不会,二我学了好像也没有用武之地。总不能跟老板说:给我几千万美金我给你撸个大模型?


dw.jpg


世界再次灰暗下来......


可是,天无绝人之路,就在我已经准备放弃的时候,我在某个产品群里看到了这样一句话:


ltjl.jpg


“???,这居然没人知道?”


过去三个月的高强度学习,在我看来在业务中找到嵌入AI的场景,甚至为了AI单独新增功能都是非常容易的事情。


AI时代已经来了,GUI到LUI是必然发生的事情,所有企业的产品都将会经历加入AI的功能或者逻辑。如果必须有一人主导这件事情的话,那为什么不能是我?


“汽车干掉马车之后,所有的司机都是之前的马车司机么?”


“计算器干掉算盘之后,所有的会计都是之前的师爷么?”


“安卓干掉塞班之后,所有的安卓工程师都是之前的塞班工程师么?”


既然都不是,那么AI带来全新的交互体验,必须是传统产品去做么?显然不是,这玩意,谁先干算谁的啊。


gds.jpg


我决定接受这个挑战,开始把视野放到应用层。开始研究产品的逻辑,尝试找到AI技术与业务需求的结合点。


不会怎么办? 学呗,这流程咱熟,报班、买书、找大佬交流。


shu1.jpg


shu2.jpg


一边学,我就一边结识了一些志同道合的伙伴,我们一起讨论、尝试、失败、再尝试。


经历过那一年的朋友应该知道,国内大模型的能力远远没有广告上说的那些效果,底层能力的限制一度成为我们思路中最大的卡点。


不过,我们也总结整理了一大批不同的产品中,不训练自己的大模型的情况下,能够结合AI的逻辑,这里简单放几个例子。



  • TOB的管理系统,新用户没办法很好的知道产品中有什么功能,可以直接通过AI助手来唤起、使用对应功能。【我很喜欢这个,典型的GUI升级LUI的场景】

  • 产品售卖,通过AI + 埋点的技术,实时分析用户的行为,在恰当的时机向用户推送VIP折扣。

  • 电商详情页浏览助手。【页面上的AI助手,也是这两年很多产品已经落地了的选择】

  • TOC的评论页面,AI拥有很好的控评能力

  • 智能问答产品,【我们认为是受到冲击最大的产品,跟AI比起来,现在市场上所有的智能问答产品,都不够智能。都应该被重做升级!】

  • 多模态能力会带来的全新产品。【情感陪伴是目前最为广泛且收益较快的赛道。】


不扯远了,说回我自己。


我的转机出现在我们自己的领导也开始说要结合AI,升级产品能力。


ddn.jpg


我以最快的速度,做好agent流程的思维导图、MVP(最小可行性产品)。 开会,给领导布道,说服领导们相信我的这套设计。


因为之前就进行过AI相关的内容分享,所以这一步比较容易。一顿操作猛如虎之后,终于获得了领导认可,接到了协助产品负责AI升级的任务,升级过程其实遇到了非常多的困难。


再次吐槽一下那一年的国产大模型,流程稍微多一点,响应时间就巨慢,流程少了,大模型的理解能力又不足。


有时候一个提示词一调就是半天,我甚至一度都要放弃了。不过好在最终我们选择了曲线救国,采用大模型+小模型,配合多专家 + RAG + 变种function call组合的架构,我们在23年底也做出了不错的东西。


上线之后,客户表示了满意。领导表示了满意。团队表示了满意。


水到渠成,后来一切就按部就班了,24年我又虚线负责了两个AI产品的升级和功能迭代。从确定需求是否适用AI实现,到方案选型,到设计agent流程,到功能上的交互设计,组织团队最终交付。


今年开始实线负责多个产品,有了自己的团队负责大模型方向的新产品设计和落地,也有需要横向拉通的部门,负责协助规划旧产品AI方向的升级和产品中AI需求的挖掘。


柳暗花明,未来可期。


结语


虽然我是前端转型到AI产品负责人的,但是如果你问我AI一定会代替掉程序员么?


我的回答是:不会,但是AI一定会让这个岗位所需要的人数减少,无论你是初级岗还是高级岗。


我们要做的就是抓住新的机会、占据有利位置、执行下去,然后等待时代的洪流将我们高高托起。


你看deepseek这不就来了? 我前面两年所做的事情,因为deepseek的出现,再次被抬高了一个维度,这就是时代,选择大于努力。



如果大家对“程序员如何转型AI产品负责人”感兴趣,可以点个赞。如果大家喜欢,后面我再多多分享转型细节。



文章更新列表


# 序员转型,带领团队落地AI产品的全流程


# 30行代码,随时进行云端DeepSeek能力评估!


# 5000字长文,AI时代下程序员的巨大优势!


作者:华洛
来源:juejin.cn/post/7469263585287651340
收起阅读 »

10年深漂,放弃高薪,回长沙一年有感

大明哥是 2014 年一个人拖着一个行李箱,单身杀入深圳,然后在深圳一干就是 10 年。 10 年深漂,经历过 4 家公司,有 20+ 人的小公司,也有上万人的大厂。 体验过所有苦逼深漂都体验过的难。坐过能把人挤怀孕的 4 号线,住过一天见不到几个小时太阳的城...
继续阅读 »

大明哥是 2014 年一个人拖着一个行李箱,单身杀入深圳,然后在深圳一干就是 10 年。


10 年深漂,经历过 4 家公司,有 20+ 人的小公司,也有上万人的大厂。


体验过所有苦逼深漂都体验过的难。坐过能把人挤怀孕的 4 号线,住过一天见不到几个小时太阳的城中村,见过可以飞的蟑螂。欣赏过晚上 6 点的晚霞,但更多的是坐晚上 10 点的地铁看一群低头玩手机的同行。


10 年虽然苦、虽然累,但收获还是蛮颇丰的。从 14年的 5.5K 到离职时候的 xxK。但是因为种种原因,于 2023年 9 月份主动离职离开深圳。


回长沙一年,给我的感觉就是:除了钱少和天气外,样样都比深圳好


生活


在回来之前,我首先跟我老婆明确说明了我要休息半年,这半年不允许跟我提任何有关工作的事情,因为在深圳工作了 10 年真的太累,从来没有连续休息超过半个月的假期。哪怕是离职后我也是无缝对接,这家公司周五走,下家公司周一入职。


回来后做的第一件事情就是登出微信、删除所有闹钟、手机设置全天候的免打扰,全心全意,一心一意地陪女儿和玩,在这期间我不想任何事情,也不参与任何社交,就认真玩,不过顺便考了个驾-照。


首先说消费。


有很多人说长沙是钱比深圳少,但消费不比深圳低。其实不然,我来长沙一年了,消费真的比深圳低不少。工作日我一天的消费基本上可以控制在 40 左右,但是在深圳我一天几乎都要 80 左右。对比


长沙深圳
5+5+
15 ~ 2525 ~ 35
10 ~ 15,不加班就回家吃25 ~ 35,几乎天天加班

同时,最近几个月我开始带饭了,周一到超时买个百来块的菜,我一个人可以吃两个星期。


总体上,一个月消费长沙比深圳低 1000 左右(带饭后更低了)。


再就是日常的消费。如果你选择去长沙的商城里面吃,那与深圳其实差不多了多少,当然,奶茶方面会便宜一些。但是,如果你选择去吃长沙的本土菜,那就会便宜不少,我跟我朋友吃饭,人均 50 左右,不会超过 70,选择美团套餐会更加便宜,很多餐馆在支持美团的情况下,选择美团套餐,两个人可以控制在 30 ~ 40 之间。而深圳动不动就人均 100+。


当然,在消费这块,其实节约的钱与少的工资,那就是云泥之别,可忽略不计。


再说生活这方面。


在长沙这边我感觉整体上的幸福感比深圳要强蛮多,用一句话说就是:深圳都在忙着赚钱,而长沙都在忙着吃喝玩乐加洗脚。我说说跟我同龄的一些高中和大学同学,他们一毕业就来长沙或者来长沙比较早,所以买房就比较早,尤其是 16 年以前买的,他们的房贷普遍在 3000 左右,而他们夫妻两的工资税后可以到 20000,所以他们这群人周末经常约着一起耍。举两个例子来看看他们的松弛感:



  • 晚上 10 点多喊我去吃烧烤,我以为就是去某个夜市撸串,谁知道是开车 40+公里,到某座山的山顶撸串 + 喝酒。这是周三,他们上班不上班我不知道,反正我是不上班。

  • 凌晨 3 点多拉我出来撸串


跟他们这群人我算是发现了,大部分的聚会都是临时起意,很少提前约好,主打就是一个随心随意。包括我和同事一样,我们几乎每个月都会出来几次喝酒(我不喜欢喝酒,偶尔喝点啤酒)、撸串,而且每次都是快下班了,某个人提议今晚喝点?完后,各回各家。


上面是好的方面,再说不好的。


长沙最让我受不了的两点就是天气 + 交通。


天气我就不说了,冬天冻死你,夏天热死你。去年完整体验了长沙的整个冬天,是真他妈的冷,虽然我也是湖南人,但确实是把我冻怕了。御寒?不可能的,全靠硬抗。当然,也有神器:火桶子,那是真舒服,我可以在里面躺一整天。


交通,一塌糊涂,尤其是我每天必经的西二环,简直惨不忍睹,尤其是汽车西站那里,一天 24 小时都在堵,尤其是周一和周五,高德地图上面是红的发黑。所以,除非特殊情况,我周一、周五是不开车的,情愿骑 5 公里小电驴去坐地铁。


然后是一大堆违停,硬生生把三车道变成两车道,什么变道不打灯,实线变道,双黄线调头见怪不怪了,还有一大群的小电驴来回穿梭,对我这个新手简直就是恐怖如斯(所以,我开车两个月喜提一血,4S点维修报价 9800+)。


美食我就不说了,简直就是吃货的天堂。


至于玩,我个人觉得长沙市内没有什么好玩的,我反而喜欢去长沙的乡里或者周边玩。所以,我实在是想不通,为什么五一、国庆黄金周长沙是这么火爆,到底火爆在哪里???


还有一点就是,在深圳我时不时就犯个鼻炎,回了长沙一年了我一次都没有,不知道什么原因。


工作


工资,长沙这边的钱是真的少,我现在的年收入连我深圳的三分之一都没有,都快到四分之一了。


当然,我既然选择回来了,就会接受这个低薪,而且在回来之前我就已经做好了心理建设,再加上我没有房贷和车贷,整体上来说,每个月略有结余。


所以,相比以前在深圳赚那么多钱但是无法和自己家人在一起,我更加愿意选择少赚点钱,当然,每个人的选择不同。我也见过很多,受不了长沙的低工资,然后继续回深圳搬砖的。


公司,长沙这边的互联网公司非常少,说是互联网荒漠都不为过。大部分都是传统性的公司,靠国企、外包而活着,就算有些公司说自己是互联网公司,但也不过是披着互联网的羊皮而已。而且在这里绝大多数公司都是野路子的干法,基建差,工作环境也不咋地,福利待遇与深圳的大厂更是没法比,比如社保公积金全按最低档交。年假,换一家公司就清零,我进入公司的时候,我一度以为我有 15 天,一问人事,试用期没有,转正后第一年按 5 天折算,看得我一脸懵逼。


加班,整体上来说,我感觉比深圳加班得要少,当然,大小周,单休的公司也不少,甚至有些公司连五险一金都不配齐,劳动法法外之地名副其实。


同时,这边非常看重学历,一些好的公司,非 985 、211 不要,直接把你门焊死,而这些公司整体上来说工资都很不错,40+ 起码是有的(比如某银行,我的履历完美契合,但就是学历问题而被拒),在长沙能拿这工资,简直就是一种享受,一年就是一套房的首付。


最后,你问我长沙工资这么低,你为什么还选择长沙呢?在工作和生活之间,我只不过选择了生活,仅此而已!!


作者:大明哥09
来源:juejin.cn/post/7457175937736163378
收起阅读 »

努力工作,你已经是很了不起的成年人了

1、像潮水一样的焦虑 "我二十三岁,靠自己的努力,全款小米Su7 Ultra。" "二十七岁,工作之余,副业一个月赚两万。" "用 DeepSeek 做副业,三天赚了九千" 对的,这些是目前互联网上短视频、问答平台、公众号里再常见不过的文案,衬托之...
继续阅读 »

1、像潮水一样的焦虑



"我二十三岁,靠自己的努力,全款小米Su7 Ultra。"




"二十七岁,工作之余,副业一个月赚两万。"




"用 DeepSeek 做副业,三天赚了九千"



对的,这些是目前互联网上短视频、问答平台、公众号里再常见不过的文案,衬托之下:



仿佛早上挤地铁四号线、一边走路一边吃热干面、坐在格子间里连喝一口水都要见缝插针、晚上加班结束要迈着飞快的脚步去赶最后一班地铁的你,是一个恬不知耻正在迈向中年的你,像是一个混吃等死毫无作为的废物。



凌晨你回到出租屋,打开朋友圈,看到的却是这样那样的焦虑:



三十天写作训练营、素人短视频日入八百、宝妈靠手作实现财务自由。



这些标题像便利店门口的霓虹灯,在深夜里闪烁得格外刺眼,仿佛在质问每个失眠的成年人:你的人生怎么还没开张?


你躺在床上,闭上眼睛的时候还在脑海里反复复盘着:“我这领个死工资也不是个事儿啊,什么时候能搞个副业,也实现一下财务自由。赚够两百万存款的时候,我要把辞职信拍到领导的脸上。”


在焦虑、自责、懊恼之余,你是否忘了什么事情?


你是否忘了,你其实是一个:


经过完整的高等教育,每天算上通勤,为工作付出超过12小时时间,没有沾染赌毒行为,勤勤恳恳态度认真的年轻人。工作之余,你唯一的爱好可能就是下班后躲在出租屋里打两把游戏。


从任何角度上看,你都是一个努力的,踏实的,积极向上的年轻人。


那么,究竟是谁在引导你否定自己的努力,对自己的状态进行 PUA 呢?


副业如果真那么神奇的话,为什么它还是 “副业” 呢?


了解那些焦虑的本质,你会发现:“副业可能是版本陷阱”。


2,副业可能是版本陷阱


我们 Dota2 玩家有个经常被挂在嘴边的词语,叫 “版本陷阱”,指的是那些版本更新之后,被大家口口相传多么厉害,但是真在职业赛场上被选出来却胜率惨不忍睹的英雄。


很抱歉,我可能要说一句丧气话:


“副业就是这个版本的【版本陷阱】。”


为什么呢?



  • 先聊副业本质


    副业的本质是跳出主页赛道,恰好进入一条机会更多、收入更高的蓝海赛道;这个机会可能来自于你自身(你恰好擅长某些主业之外的能力),更多的时候来自于时代红利(早几年间你非常擅长制作短视频)。


    因此,少量时间+副业可以带来高收入的本质,是个人长项在蓝海领域博取一个创收机会,但是你先问问自己,有没有主业之外领域的优势技能。


  • 再说版本环境


    在上一条里面我们提到了“蓝海行业”,这一点非常重要,只有某个赛道出现明显的技术缺口或人员缺口时,副业者才有腾挪的空间。但如果一个行业或赛道已经人满为患,你准备拿每天2个小时和那些每天12个小时的团队作战吗?


  • 最后分析下“口口相传”的那些人


    你以为天天分享副业赚钱的人群:“人生导师、大公无私、先富的来带动后富的。”


    实际发那些文案的人群:那些教你"睡后收入"的博主,自己往往在通宵直播卖课;晒着海岛定位说走就走的旅行博主,回程机票可能都是网贷分期。这个魔幻的时代,连贩卖成功学的都在996加班。


    而他们兜售焦虑的最后一环,还是希望焦虑者咬上他们那锈迹斑斑的铁钩,成为下一个为“财富自由”付费的“上进者”。



请容许我再说一句丧气话:



绝大多数普通人的搞钱手段就是上班,只有上班。



哪有那么多暴富的机会在前方等着你?哪有那么多“睡后”的收入在梦中等着你?哪有那么一劳永逸又无比轻松的战役,在彼岸等着你。


你之所以相信彼岸的美好,有没有可能是因为你看不穿横在河面上的浓雾?


3,努力上班,已经是很棒的成年人了


每天我总能见到大家在各种空间和途径输出焦虑:



女孩责怪男孩不上进,下班只知道打游戏。




男孩抱怨不该生孩子,没有时间和机会创业搞财富自由。




总有人和自己身边的成功同龄人做比对,反思得出“自己是个废物”的神奇结论。



可是啊同学,我们也只是一群普通人而已。


在步入三十五岁之后,变成互联网行业里的“下岗预备役”之后,我逐渐开始认清了自己的属性和位置,不再苛求自己与众不同。


经过完整的高等教育,每天算上通勤,为工作付出超过12小时时间,没有沾染赌毒行为,勤勤恳恳态度认真的年轻人。工作之余,你唯一的爱好可能就是下班后躲在出租屋里打两把游戏。


每周可以有时间陪家人一起做一些不花钱的娱乐。


每周可以有时间陪孩子梳理一下近期的学习、分享一下思考。


每周有那么几个小时可以做一些让自己从内在感到快乐、感到满足、感到宁静的事情。


你没有去赌博欠下一屁股债,没有去加杠杆投资卖掉父母的房产,没有闷着头贷款创业亏光爹妈的棺材本。


同学,你可能意识不到,但我今天非常想郑重地告诉你:



在成年人这个群体之中,你已经是非常杰出、非常棒的那一批了。



副业焦虑?让它见鬼去吧。


作者:摸鱼的春哥
来源:juejin.cn/post/7481187555866804224
收起阅读 »