在独立域名持续创作博客,是最简单的长线投资

我很喜欢看博客, 尤其是兴趣使然的独立博主写的博客, 博客是很好的灵感来源。比如我看到《大数据已死》这篇文章, 就会了解到通过分离存储和计算, 大数据作为单一问题就不存在了,变成了海量存储和大型计算两个问题, 而且这两个问题各自都能通过独立扩展,进行解决。

我很喜欢写博客, 因为博客能促进人思考, 每天上班工作, 如果没有写博客的习惯, 很容易就会被工作所淹没,工作中的思考也很难被记录下来。

博客比书籍发布内容更快,而且是免费的! 有些领域变化非常快,在有人写书之前,博客有时是唯一的信息来源。Stable diffusion 模型出现后的第二天,人们就已经在写博客了,书籍永远不会那么快。而书籍和论文则被锁定在付费墙之后, 加之自媒体经济产生大量垃圾书籍, 买书像是抽盲盒。

持续创作博客是最简单的长期投资,我2016年开始在简书写博客,用免费开源的WordPress做个人网站,在Github更新各种个人开源项目,这些时间如果用来玩游戏,刷短视频,也便荒废掉了,写(技术)博客则是把时间储蓄了起来,提升专业水平,帮助一些人,也收获一些朋友。

实践比转发更有乐趣,2023年3月,各种非人非狗的媒体为了流量,在它人的苦难面前,开始自我治愈,还开始调侃鲁迅先生笔下的孔乙己,如果鲁迅先生还拿的动笔,肯定要提笔锤爆这群标榜中肯的无良媒体,有人在转发反驳的观点,但我感觉还是亲自骂一骂才过瘾,亲自骂一骂才能有更多的语料,为无良媒体的早日倒闭丢一块飞砖。

水滴石穿,为未来做准备,内容平台自我阉割的越来越厉害,中文互联网就变得只剩下一种声音,如果想发出不同的声音,请准备一个独立的域名,独立域名的内容可以被搜索引擎抓取,随着域名年龄的增长,上传内容的增多,自己认可的声音,也可以通过古老的域名向互联网布道,优质的域名,本身是资产。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-18-15-27-38-read-book/

程序员学哪一门语言更不容易失业

今天,大学室友微信群在聊一个很经典的话题,程序员学哪一门语言更不容易失业

有人认为PHP已经到了黄昏,有人认为Go语言可以和Java掰一下手腕,有人认为没有什么是一行sql解决不了的,有人认为 Python和Java永远是主流,能干到头秃… (有研究表明,程序员与秃头并没有太大的相关性,研究并不一定准)

我的观点是,javascript和 Node.js配合,更不容易失业,JS这门语言应用极为广泛,几乎什么都能做,Web小程序(React),App开发(React Native),桌面应用(Electron)都可以用js写,是万金油一般的存在。

JS这门语言易上手,上限很高,从业者众多,依赖包生态也极为丰富,神库众多,即使你的水平一般,也能借助各种神库,写出健康的代码,保持健康的发量

JS深度绑定Web生态,JS是Web生态的基石,Web是互联网的基石,互联网技术越发展,JS的内容层次就越丰富,同时也意味着,JS程序员要不断学习,才不会被后浪拍在沙滩上,说穿了,想要不失业,就要不断学习

JS是最接近前端的语言,前端是最接近用户的,如果想要证明自己的编程实力,可以自己搞开源项目,而JS很适合搞开源项目,一个周末写个油猴子增强插件不是梦~

在2023年,很多人在喊前端已死,我认为初级水平的前端可以被机器取代,但JS程序的基数极为庞大,如果拥有对JS程序调优的能力,那就不容易失业,如果能用ChatGPT这类工具提升开发效率,那反而会让我们的工作更轻松。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-16-16-24-25-js/

摄影天然适合程序员

程序员的脑力劳动远大于体力劳动,写个人博客是很好的爱好,但脑力不足的时候,摄影是程序员天然的生活调味剂。

  • 摄影增加运动量,提升程序员的体力,多走多拍才有好照片,摄影给久坐的程序员一个锻炼的机会,努力锻炼,保持健康,活得久比什么都重要。

  • 摄影教会程序员做减法,提升程序员审美,微软的程序大多功能丰富,毫无设计感,而好的摄影作品讲求明确主体,突出主题,简化画面,懂得做减法的程序员能前往更高的境界。

  • 摄影扩大程序员折腾的范围,找到更多可玩的领域,Adobe全家桶,相机raw解码软硬件,照片原片的存储备份,不同焦段原副厂镜头的选购,走山访海旅行计划的制定,游戏摄影配套插件工具的优化,都能扩大程序员的折腾范围,这些恰好都和程序相关。

  • 摄影是一门下限很低,上限极高的学科,如果一门知识的上限很低,便不可持续,而摄影的上限很高,即使到了70岁,我们只要出门打开取景器,就可能拍出比以往作品都更好的照片,持续向上发展的兴趣,能给程序员更好的人生体验。

  • 摄影容易交到朋友,扩大程序员的社交范围,程序员大量的时间都被工作占据,交朋友的时间很少,而摄影这项爱好,能让我们通过同城摄影群,交到各行各业的朋友。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-16-16-11-43-programmer-photography/

我为什么喜欢用锤子便签

锤子便签配色舒服,适合阅读,锤子便签用户界面一直是暖色,背景与文字的配色都很舒服,无论是创作者还是阅读者,都有很好的观感。

锤子便签免费且没有广告,锤子便签没有搞订阅制,也没有广告,属于真正小而美的软件。

锤子便签有Web版!我认为一个工具良不良心,支持web是很重要的指标,支持web就意味着可以在任何可以安装浏览器的设备使用,即使你是Linux用户。

锤子便签支持多端同步,无论是安卓,iOS,还是PC web版都能顺利同步进度,对于拥有碎片化时间的人,我们可以在床上用iPhone或安卓手机写,起床后可以用PC或Mac接着写。

锤子便签生成的图片分辨率很不错,锤子便签生成的图片适合发布在各种社交媒体,文字不失真,排版工整细致,图片适合阅读,也方便下载存档。

锤子便签默认字体很周正,适合发正式的通知,非衬线字体适合发通知,锤子便签字体很适合发布通知内容。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-16-16-04-56-smartisan-notes/

建议Apple推出新表带:你大爷永远是你大爷!公园唱歌老大爷才是Apple Watch的核心用户

在深圳莲花山公园闲逛,遇到一位老大爷唱歌,周围很多阿姨围观,仔细观察,发现老大爷的手表是Apple Watch!

深圳莲花山公园Apple Watch老大爷其一

深圳莲花山公园Apple Watch老大爷其二

老大爷或许才是Apple Watch的核心用户,关注自身健康,喜欢手表,退休金充裕,配合iPad 可以组个K歌全家桶,而且Apple Watch 还支持电子木鱼App,没事可以敲两下,功德加一

建议库克出个老大爷专属表带,表带名为:「你大爷永远是你大爷」(手动狗头)

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-23-12-51-18-apple-watch/

独立博客永不为奴

2023年2月,微信公众号图文推送样式,逐渐向小红书看齐,于是我体验了一下小红书的发文功能。

总体来说,小红书发文体验比公众号编辑器好很多,公众号编辑器,无论是网页版还是app版,体验都很烂,外链图片经常转存失败,图片转存失败后,其余内容也强制无法保存。

微信公众号目前的问题

新申请的公众号一律没有评论功能,没有评论,就无法建立创作者与读者之间的交流

推送倾向展示量大而多的公众号,一些追求品质的年更月更创作者,无法将内容传递给粉丝

公众号审核规则不透明,每个平台的审核规则都不透明,小红书也是如此,我在小红书昵称定为老法师昭昭都被判定违规,想要完整表达自己的观点,还是得有自己的域名,独立博客永不为奴

公众号内容生态完全封闭,创作者无法向广阔的互联网展示自己的内容,用人话说,就是内容再好,别人也搜不到。

公众号已发布的内容无法修改(准确说,只能修改正文的几个字),配合无评论功能的限制,内容一旦发布,即使发现了严重错误,也无法修改,只能删除,而公众号每天还有群发限制,及时改错的想法基本凉凉… 小红书在这方面就做的很好,甚至可以修改封面图!

小红书用起来不爽的几个点

小红书完全不支持外链,小红书将个人博客的外链视为引流违规行为,所以小红书无法做连续的合集内容,只能做碎片化的内容。

小红书的审核规则很随意,一张图放到推文内容中可以,但设置为个人页背景封面就判定违规。

小红书会ban掉海外IP访问,国内创作的内容,无论是什么语种的内容,都只能自产自销,有点无聊…

独立博客永不为奴

我认为,能把自己的想法完整表达出来,并传播出去,应该是创作者的基本权利,而内容上了公共平台,能不能发,能发哪一部分,就由不得创作者了

创作者利用公共平台,放大自己的影响力,而公共平台也在驯化创作者,最后创作者变成了不愿思考,只研究流量规则的自媒体。

上周,阮一峰老师的博客,受到了入侵,恢复内容用了两三天;我的个人博客(文末)最近也不断收到大量的垃圾评论,长期消耗本就不富裕的服务器资源。

个人独立博客越来越难做,但也越来越有吸引力,当所有平台都在捂创作者的嘴时,能有一个名为个人独立博客的方式,还能允许我自由表达,如同黑屋子开了一扇窗,我会感到很欣慰,独立博客永不为奴!

兽人永不为奴

微信公众号创造了内容孤岛,ChatGPT这类产品,会是将孤岛连接到开放互联网的航路。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-23-12-30-38-blog/

ChatGPT是一个理解自然语言的工具箱

ChatGPT的话题在2023年2月格外火热,以聊天对话的形式,为人类提供大量的专业知识。

万能的神ChatGPT

ChatGPT 擅长产出符合逻辑的答案,人类的逻辑能力其实并不好。作为一个开发工程师,我发现代码80%的BUG,都是程序逻辑有问题,即使是常年写码的工程师,也会写出逻辑有问题的程序,ChatGPT非常适合排查代码片段,辅助工程师写出逻辑正确的代码,在这方面, ChatGPT最大的竞品是Github Copilot

Github Copilot

ChatGPT拟人化的问答模式,非常适合当老师。学会一门知识,本身是枯燥的,如果把知识转换为ChatGPT问答的形式,将会极大提升课堂的趣味性,玩过RPG游戏的人,要进行大量的问答,这些问答往往是几个固定的问题,再给几个固定的选项,如果将知识转换为RPG游戏的形式,并给予极大的问答自由度,学生就变成了玩家。

ChatGPT适合仿制3A游戏,3A游戏需要大量的人力,海量的资金投入,巨长的开发周期;引入ChatGPT,游戏开发者只需定义玩法,ChatGPT就可以生成中规中矩的罐头游戏,罐头游戏并非贬义词,市面上绝大多数游戏都是没什么特色的罐头游戏,ChatGPT能生成罐头游戏,反而让开发者们,更有时间去研究特色玩法。

ChatGPT适合生成产品发布会,因为发布会的套路都是固定的;ChantGPT也适合做直播,因为直播的套路也是固定的;ChatGPT最适合做的是公务员,我们一直谈法制,但不好搞,ChatGPT代替法官来判案,代替律师来辩护,会让罪与罚更容易一一对应。

ChatGPT 会员终于开放了,支持万事达,Visa,每月20美元,开通后有两个模型可选,开通会员后,会默认使用提升回答速度的版本,当然也可以选择普通速度的Legacy版本。

ChatGPT会员可选两个模型

买ChatGPT PLUS会员并不容易,需要用海外信用卡支付,我办了Depay的海外万事达卡,特色是支持USDT充值,如果50美元开卡,可以免月租;如果需要海外信用卡,可以通过我的邀请链接开卡 https://depay.depay.one/web-app/register-h5?invitCode=620375&lang=zh-cn

ChatGPT非常适合写脚本,但小概率会出现类型错误,变量名的语义和实际进行的操作产生了误差(命名不规范坑人也坑ChatGPT)

ChatGPT生成代码错误

ChatGPT可以帮忙写很多前端样式,对汉语描述的理解非常到位,我们还可以不断追加要求,要求ChatGPT对代码进行改写,真的是理想的乙方

ChatGPT写样式

ChatGPT改写代码

让ChatGPT用Node.js写一个同步脚本

  • 输入需求
写一个基于rsync命令同步服务器目录(比如 /opt)到本地目录(比如 ~/cloud-backup/ )的Node.js每日定时备份脚本;

支持配置登陆用户, 和登录服务器信息, 服务器IP, 登录端口, 登录用户, 无需配置密码, 默认使用ssh key登录;

每天的备份目录用YYYY-MM-DD日期格式命名,如果从服务器同步的文件夹为 `/opt/` , 则在本地的存放位置为 `${用户目录}/cloud-backup/YYYY-MM-DD/opt/` ,传输速度限制为每秒100KB,如果同步失败, 则1分钟后自动重试, 只保留最近14天的备份, 过期的备份自动删除;

如果本地文件夹不存在,则自动创建;

同步过程中, 打印同步文件进度的log; log同步输出到脚本同级目录下的log.txt文件, log.txt只保存最近14天的log, 过期的log自动删除;

将功能点细分为函数, 便于后续扩展;

列出以上脚本依赖包相关的 package.json

我需要使用pm2守护运行这个脚本,请给出pm2凌晨2点25分运行脚本的方法

ChatGPT输出代码

const { exec } = require("child_process");
const { format } = require("date-fns");
const fs = require("fs");
const path = require("path");
const { promisify } = require("util");

const execAsync = promisify(exec);

const SSH_KEY_PATH = process.env.SSH_KEY_PATH || "~/.ssh/id_rsa";
const SYNC_FOLDER = "/opt";
const BACKUP_FOLDER = `${process.env.HOME}/cloud-backup`;

const SSH_CONFIG = {
  host: "example.com",
  port: 22,
  username: "example",
};

const MAX_SPEED = 100; // KB/s
const RETRY_INTERVAL = 60 * 1000; // 1 minute
const MAX_BACKUPS = 14;

const now = new Date();
const backupFolderName = format(now, "yyyy-MM-dd");
const backupFolderPath = path.join(BACKUP_FOLDER, backupFolderName);
const logFilePath = path.join(__dirname, "log.txt");

async function syncWithRetry() {
  let success = false;
  while (!success) {
    try {
      await sync();
      success = true;
    } catch (err) {
      console.error(err);
      console.log(`Sync failed, retrying in ${RETRY_INTERVAL / 1000} seconds...`);
      await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
    }
  }
}

async function sync() {
  const command = `rsync -a --progress --max-size=${MAX_SPEED}K --delete -e "ssh -i ${SSH_KEY_PATH}" ${SSH_CONFIG.username}@${SSH_CONFIG.host}:${SYNC_FOLDER} ${backupFolderPath}`;
  console.log(`Syncing ${SSH_CONFIG.username}@${SSH_CONFIG.host}:${SYNC_FOLDER} to ${backupFolderPath}...`);
  await execAsync(command);
  console.log("Sync finished.");
}

async function removeExpiredBackups() {
  const backupFolders = await fs.promises.readdir(BACKUP_FOLDER);
  const expiredBackups = backupFolders
    .filter((folder) => folder !== backupFolderName)
    .sort()
    .slice(0, -MAX_BACKUPS);
  await Promise.all(
    expiredBackups.map((folder) =>
      fs.promises.rm(path.join(BACKUP_FOLDER, folder), { recursive: true, force: true })
    )
  );
}

async function removeExpiredLogs() {
  const logs = await fs.promises.readdir(__dirname);
  const expiredLogs = logs
    .filter((log) => log.endsWith(".log") && log !== `${backupFolderName}.log`)
    .sort()
    .slice(0, -MAX_BACKUPS);
  await Promise.all(expiredLogs.map((log) => fs.promises.rm(path.join(__dirname, log))));
}

async function createBackupFolder() {
  try {
    await fs.promises.mkdir(backupFolderPath, { recursive: true });
    console.log(`Created backup folder: ${backupFolderPath}`);
  } catch (err) {
    if (err.code !== "EEXIST") {
      throw err;
    }
  }
}

async function main() {
  await createBackupFolder();
  await syncWithRetry();
  await removeExpiredBackups();
  await removeExpiredLogs();

  const logText = `Synced ${SSH_CONFIG.username}@${SSH_CONFIG.host}:${SYNC_FOLDER} to ${backupFolderPath} at ${new Date().toISOString()}\n`;
  await fs.promises.appendFile(logFilePath, logText);
}

main().catch((err) => console.error(err));

如果输出中断,我们可以要求ChatGPT继续上次的输出,而不用重新生成

继续输出

内容输出

然而,ChatGPT 还是漏了package.json的输出,我们可以要求ChatGPT对package.json内容重新输出

image-20230219152951399

前面我们明确要求了ChatGPT进行函数式编程,如果我们需要优化某个函数的输出,可以直接让ChatGPT继续修改

继续修改

运行ChatGPT修改后的脚本

运行结果

修改后的脚本可以顺利完成同步任务,由于rsync可以自动跳过已同步的文件,当天,多次运行同步脚本,也可以快速进行增量同步。

让ChatGPT推荐一些WordPress主题

WordPress主题推荐

如果我们有自己的WordPress网站,个人服务器带宽有限,首屏打开速度不理想,也可以让ChatGPT给出一些轻量化主题推荐

小结

2023年,用中文在搜索引擎(Google, Bing, baidu)查点儿东西(凯恩斯陷阱),大概率都会指向知乎,但知乎产品又做的非常粪坑,强迫用户装App, App各种无厘头的弹窗广告,搞的推荐和热榜话题简直是兢兢业业的给用户喂shi

凯恩斯陷阱

ChatGPT确实可以当搜索引擎来用,用中文问内容,几乎是有问必答,而且干净无废话,不懂还可以追问,一言以蔽之,搜索引擎本身也不生产内容,和ChatGPT一样,都是内容的搬运工,但ChatGPT和搜索引擎的用户体验简直是天壤之别,而且ChatGPT还可以通过加入新数据,不断成长,搜索引擎确实应该努努力了,一个无法持续优化的搜索引擎,是无法和ChatGPT竞争的。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-12-11-51-20-chatgpt-tools/

zhaoole推荐值得玩的主机游戏

塞尔达旷野之息

异度神剑2

异度神剑3

女神异闻录5皇家版

最终幻想7重置版

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-12-11-23-42-game/

编程小技巧:尽早汪汪汪的狗才是好狗;少用胶水;避免被僵尸吃掉脑子

尽早汪汪汪的狗才是好狗

我们的工作是去野外采摘药草,然后卖给药店,为了提高效率,我们打算买条狗,此刻有甲乙两条狗,可以购买...

甲狗:一旦发现药草,就立刻汪汪汪!

乙狗:发现药草后,默不作声,然后向随机方向走上100米,然后汪汪汪...

我们应该选择哪条狗?乙狗显然没啥用

对应到日常编程中,我们的代码,接收到不合理变量输入时,应尽快报错(汪汪汪),而不是等到程序崩溃了,再去回头找错误

少用胶水

我买了个手办,需在墙上固定一个木板,把手办摆上去,有两个方案:

方案A: 搞瓶胶水,然后把木板侧面与墙粘合在一起。

方案B: 在墙上打孔,然后在孔里加两根棍,形成一个支架,在支架上放一个木板。

胶水方案方便,问题在于,黏到墙上,就完全无法调整,而支架可以加小垫片精调。

需求也会随时间变化,多放几个手办,胶水粘性无法承担更大的重量,自然被废弃。

写码不是一锤子买卖,要留出精调的参数,也要方便修改,适应不断增长的需求

避免被僵尸吃掉脑子

内存泄漏是一个经典问题,用Javascript写程序,我们需要使用定时器,监听器,如果我们用完后忘记清理,就会造成内存泄漏。这些定时器,监听器就像一只只僵尸(Zombies),在地下室里蹒跚而行(参考植物大战僵尸中的普通僵尸)

僵尸

这些幽灵般的不死不灭的僵尸会吃掉大脑,让记忆外泄(内存泄漏), React Hook这类工具也给出了 useEffect return 函数的方式,专门清理这些僵尸;

内存泄漏无小事,关注代码运行的副作用,规范编码,不要让僵尸吃掉脑子

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-04-14-57-27-good-code/

土地财政锁死了中国年轻人的未来,买房变租房,一念天地宽

原贴 本人目前是码农,关于是否要在 35 前进入体制内,和女朋友有了如下对话,不知道大家怎么看 https://v2ex.com/t/912179

本人目前是码农,关于是否要在 35 前进入体制内,和女朋友有了如下对话,不知道大家怎么看 - V2EX - v2ex.com

在V站看到篇帖子,发帖的老哥和他女朋友因为房子,体制,35岁后码农就业的问题,进行了一波儿深入的探讨。

我的看完后的,直观感受是,这也太没劲了。作为一个程序员,我和帖子中的老哥处境类似。

作为一个创业公司的程序员,我连下个月做什么需求都无法确认,当然也无法预测10年后某地段的房子会不会升值。

为了10年后所谓的资产升值,疯狂压榨当下的自己,并不是正常的做法。

儿孙自有儿孙福,如果父母很聪明,下一代的智商,大概率是比不上父母的,但智商比不上父母,并不代表下一代不幸福,还未结婚,就考虑下一代孩子阶级跌落,本就是一件很无厘头的事,那些疯狂鸡娃的人,就好比是宫崎英高世界里追求永生的人,无一例外全是悲剧。

我所在的小区,离腾讯滨海大厦很近,有三十多层楼,距今已有二十年,我感觉已经不太宜居了,物业也都是50岁左右的人,配合超高的楼层,再过十年,不知道还有多少户人家。

人要给自己留余裕,不要勉强自己,活得久比什么都重要。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-01-20-08-34-it/