技术日记

2024

6月小结

TODO

07/01

Github 上发现的开源大佬

今天上班的时候摸鱼刷 Github 刷到一个做 MIT6.828 实验的大佬,点进主页一看还真的是个大佬

看到他的自我介绍,高中毕业的学历,18 年 28 岁转行程序员,自学前端,一步步走到管理层,感觉很有兴趣,肯定有值得学习的地方

虽然如果 18 年换成六年后的今天,同样的情况几乎不可能实现,18 年的计算机行业算不上黄金的红利风口时期,但是也远没有到今年的地步,在感慨他人恰逢一个好的时代的同时,不得不肯定的是这个老哥的自学能力以及对技术的追求和热爱

其中他的开源文章就分享了一些从业前端和管理方向的开发者工作心得,觉得很有用,记录一下:

  • 一个好的程序员必须得懂业务,但是和写不写业务页面关系不大,就算是搞基础架构也需要懂业务,你得明白公司靠什么赚钱,脱离了业务讨论都是扯淡
  • 找工作的时候心态很重要,或者说生活中的任何事情,心态都很重要。面试是双向的选择,不是候选人在求着别人给工作,所以面试时不要把自己的位置放得太低。面试也是一件很讲运气的事,通过不了不一定是你技术不行,很有可能是问的问题刚好你不会(位置对调,面试官也有可能通过不了面试)、气场不合、价值观不符合等等。面试挂了做下复盘再准备下一次面试,不要在一棵树上吊死
  • 计算机基础是地基,决定了一个程序员的技术上限。管理系统写得再好,也只能证明你是一个熟练业务操作的人员,想要成为行业拔尖的水平,想要铸就不可替代性,需要的是计算机基础,任何框架和第三方库都是基于基础设施的高层建筑,基础打好了,楼才能建得高
  • 其中还提到了作为一个程序员的学习方式,内容比较多直接提取出来单独成一点
  • 通常情况下,技术和薪资成正比
  • 技术好的人比较自信,脾气也比一般人暴躁
  • 不要裸辞,找好下家再辞职
  • 涨薪基本靠跳槽
  • 同事有可能会成为朋友,但最终都是过客
  • 要有职业规划,没有就去想,直到想出来为止
  • 面试造航母,工作拧螺丝不是玩笑话
  • 要学会心平气和的跟产品沟通,尤其是不懂技术的产品,虽然很难
  • 每天写业务页面不能让你变强,顶多算是比较熟练的流水线工人,要变强还得靠业余时间
  • 喜欢学习的程序员很少,得过且过才是大多数
  • 工作不忙时,尽量利用这段时间学习;技术越好,任务完成得越快,摸鱼的时间就越多
  • 少管闲事,有时间多学习
  • 少关注八卦新闻,多学习
  • 别拍马屁,有那功夫多学习
  • 时刻反省自己,今天有没有学习

学习方式

主要有两种:

  • 知识固化,写作
  • 灵魂三连问

知识固化这个就不多说了,之前其实也在 游戏札记 这一系列文章中提到了,可以将学习到的知识尽可能的记忆下来,强化记忆。同时也能锻炼自己的表达能力,一个程序员必须需要具备优秀的表达能力,才能在职场中进行有效的沟通交流。此外,能把自己每日的学习总结提取成一段精炼的文字,也是理解能力的一种表现。

至于这个灵魂三连问,主要是说:在学习新的知识点时,时常问自己三个问题:

  • 这是什么?
  • 为什么要这样?可以不这样吗?
  • 有没有更好的方式?

CSAPP 流水线

回家后主要还是在学习 CSAPP 的汇编条件控制部分知识

之前教授上课讲到的为何需要 Conditional Branch 技术,之前流水线技术听的一知半解,现在配合博客总算是有了大概的概念

大致的意思就是由于 CPU 的流水线技术,编译器需要尽可能地减少错误的分支判断,一旦判断失误进入了错误的分支,先前因为流水线技术而加载进入寄存器的数据全部都是对不上号的了,因此需要进行分支预测来优化程序的执行

针对仅仅只有两种条件跳转的代码(例如三元运算符),编译器往往就会采用 Conditional Branch 的技术,通过枚举出所有可能的结果状态(实际上也就只有两种),最后根据一条比较指令来同时设置结果值,从而不会进行跳转,实现性能的优化

同时我们也分析了采用这种 Conditional Branch 的技术局限性,具体适用于什么场景,当然这些是编译器设计需要考虑到的因素之一了

07/02

久违的基础课环节

学习 CSAPP 的汇编

07/03

极速原型是个好东西

化身产品经理画项目原型图 XD

xiaopiu 这个原型图网站我也算是懂得了一些了,能够简单拖拉拽开发产品原型,并且进行简单逻辑跳转用于演示,不得不说确实方便

07/04

业务和技术都重要

今天部门同事聚餐,聊了一会,感觉还是业务和技术都很重要

入职到现在对于中台项目的业务流程还是不太了解,当然更重要的业务还是金融方面的业务知识了,这些都是需要时间沉淀下来的

台式机部署一下MySQL8

回家刚好部署了一下 MySQL8 感觉还是踩了一点坑,这里记录一下

  • 去官网下载最新的开源社区版
  • 之后解压,新增 my.ini 配置文件,同时配置 bin 目录为系统 path 环境变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[mysqld]

# 设置3306端口

port=3306

# 设置mysql的安装目录

basedir=D:\Coding\mysql-8.4.1-winx64

# 设置mysql数据库的数据的存放目录

datadir=D:\Coding\mysql-8.4.1-winx64\data

# 允许最大连接数

max_connections=200

# 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统

max_connect_errors=10

# 服务端使用的字符集默认为UTFMB4

character-set-server=utf8mb4

# 创建新表时将使用的默认存储引擎

default-storage-engine=INNODB

# 默认使用“mysql_native_password”插件认证,这里注释掉了,不注释掉会报错启动服务失败

# default_authentication_plugin=mysql_native_password

[mysql]

# 设置mysql客户端默认字符集

default-character-set=utf8mb4

[client]

# 设置mysql客户端连接服务端时默认使用的端口

port=3306

default-character-set=utf8mb4
  • 此时还没有 data 目录,问题不大,启动服务的时候会自动生成创建对应的目录,我们输入命令生成 root 的密码

    1
    mysqld --no-defaults --initialize --console
  • 之后会在控制台显示对应的密码

  • 输入 mysqld --install mysql 安装服务
  • 启动 mysql 服务 net start mysql

上面的配置文件中 default_authentication_plugin=mysql_native_password 之前没有注释掉,导致启动报错,找了好久也不知道为啥,后面通过 mysqld --console 输出启动日志,才发现是报错信息中提到了 [ERROR] [MY-000067] [Server] unknown variable 'default_authentication_plugin=mysql_native_password'. 目前的 MySQL 版本无法读取这个配置,可能是已经过时,注释掉之后正常启动

  • 之后连接到本机的 MySQL 进程第一件事修改密码 alter user 'root'@localhost identified by '1'

07/05

还是在修改业务上的一些东西以及原型图的绘制

你问我回家干什么了,抱歉,今天是周末!

07/08

斗胆升级IDEA2024

主要是想用新版的 JDK,但是之前一直用的是祖传的 2021 版本,最多只能支持到13还是多少,反正17之后就检测不到对应的新的 JDK 了,加上想试一试新的 UI 风格 (VSCODE),直接痛定思痛,卸载旧版!

这里用的是脚本激活,一键自动配置激活补丁

首先去官网的 other version 部分下载 2024.1.3 的版本

之后一路安装,安装好了以后先启动

第一次启动比较慢,不是没启动,只是启动很慢,等第一次弹窗出现后,点击 quit 不进行激活

然后进入 进入 /jetbra 补丁目录,再点击进入 /scripts 文件夹,双击执行 install-current-user.vbs 脚本

等个半分钟,出现 done 了之后才算是完成

脚本会自动在环境变量 -> 用户变量下添加了 IDEA_VM_OPTIONS 变量,变量值为 /jetbra 文件夹下的 .vmoptions 参数文件绝对路径,然后,脚本自动在 idea.vmoptions 文件中引用了补丁

之后输入指定的激活码

1
6G5NXCPJZB-eyJsaWNlbnNlSWQiOiI2RzVOWENQSlpCIiwibGljZW5zZWVOYW1lIjoic2lnbnVwIHNjb290ZXIiLCJhc3NpZ25lZU5hbWUiOiIiLCJhc3NpZ25lZUVtYWlsIjoiIiwibGljZW5zZVJlc3RyaWN0aW9uIjoiIiwiY2hlY2tDb25jdXJyZW50VXNlIjpmYWxzZSwicHJvZHVjdHMiOlt7ImNvZGUiOiJQU0kiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBEQiIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiSUkiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQUEMiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBHTyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNXIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQV1MiLCJmYWxsYmFja0RhdGUiOiIyMDI1LTA4LTAxIiwicGFpZFVwVG8iOiIyMDI1LTA4LTAxIiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQUyIsImZhbGxiYWNrRGF0ZSI6IjIwMjUtMDgtMDEiLCJwYWlkVXBUbyI6IjIwMjUtMDgtMDEiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFJCIiwiZmFsbGJhY2tEYXRlIjoiMjAyNS0wOC0wMSIsInBhaWRVcFRvIjoiMjAyNS0wOC0wMSIsImV4dGVuZGVkIjp0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

07/09

CRUD 需求远没有那么简单

今天主要还是分析项目的需求,感觉实际行动起来会比以前接触到的需求复杂不少,并不是简单的 CRUD,同时 CRUD 也远没有想象中的那么简单

能把 CRUD 写得好,也是一种本事

一名合格的高级程序员必须要具备抽象应用需求场景,快速建立实现需求模型的能力,显然我现在还需要在实际的生产项目中进行锻炼

07/10

如何优雅的设计表

今天学习了如何优雅的设计目录树层级表

后续有时间的话可能会整理成为一个专题文档

似乎需要补一下 SQL 基础了

今天写需求,猛然发现自己 SQL 知识差不多忘得一干二净了

是时候拿起之前的笔记和文档课程,系统性地再过一遍 SQL 基础知识了,一些联表查询语句似乎还不是很熟练,框架封装了那么多,对于实际的开发,到底是好是坏?索引数据结构,现阶段而言真的没有必要了吗?需要带着问题重新学习

通义灵码确实好用

今天正式在项目中引入了通义灵码插件,颇为震撼

除开代码段的分析,自动生成注释,内置 GPT 问答外,这哥们还会自动补全

我就敲了一个枚举的签名,这哥们直接给我写完了,当然大部分的数据可能还是不需要采纳的

07/11

一份项目关联两个仓库实现远程开发

最近的需求就是有的时候回家还要看代码,但是懒得回家还背一个电脑

回家直接用台式进行开发,那么笔记本和台式之间项目的开发进度同步就成了一个问题

每次下班之前都进行提交到公有的仓库显然是不现实,我采取的方案是:

  • 在公司内网的 GitLab 中再创建一个私有的个人仓库,对应在本地拉一个新的个人开发分支用于存放每一次的琐碎提交记录

  • 项目新增远程关联,个人开发分支每次都推到个人仓库,不污染公共仓库

  • 开发完毕需要合并 Commit 的话直接一个 Rebase 就完事

  • 至于个人私有仓库积累的琐碎记录,也是一个 push –force 就可以覆盖

首先新建一个仓库

之后在本地仓库中新增 remote 关联

1
git remote add private xxxx # 新增名为 private 的远程关联,当然也可以直接在 IDEA 中点

之后可以查看配置信息

1
2
3
4
5
6
7
8
remote.origin.url= 公有仓库.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
remote.private.url= 私有仓库.git
remote.private.fetch=+refs/heads/*:refs/remotes/private/*
branch.private-master.remote=private
branch.private-master.merge=refs/heads/master

推送项目到私有的远程仓库,注意是 private 不是 origin ,别推错了

1
git push private master

我们在本地开发环境针对 private 远程关联的 master 新拉一个分支 private-master,以后所有的琐碎提交都在这里进行

切换到新的本地分支

1
git checkout private-master

尝试 update 同步远程的更新,但是报错 couldn't find remote ref refs/heads/private-master

这个主要是因为我们针对 private 远程拉的分支名称是 private-master 默认在更新的时候会同步 private/private-master,但是 private 远程实际上并不存在这个分支,因此就报错了没有切换到对应的 private-master 分支导致的,在 master 分支下的状态进行操作,就会报错

我们可以修改本地分支名称来解决,但是已经有 master 分支名称了不能重复,因此可以直接修改引用

1
2
git checkout private/master #一定要先切换到对应 private 远程的分支,别改错了
git push -u private private-master:master # 推送的时候同时修改上游追踪的映射关系

看来 Git 还是需要不断练习,不管再多的命令学习都是纸上谈兵,实际需求一来才是锻炼

生日加班

今天是我的新历生日

想着回家可以放松一会奖励自己打回电动

结果下午群里就通知要开始固定加班了XD

第一天加班体验还算不错,感觉上算是有高中晚自习那味了

差不多七点开始干活,到了九点差不多也就走了,高中晚自习差不多也是这个时间

后续一段时间估计会很忙,希望自己能坚持住吧

07/12

动手才是王道

今天是周五

但是没有了周五的味道

下周开始要开启地狱加班模式了

只能说明天还得继续写代码,想想怎么处理业务

今天尝试动手试了一下之前一直觉得很复杂的业务逻辑,没想到一次就成了,都没有报错

果然还是动手尝试比坐在那边空想有用

AI生产内容还是不太可信

我让AI生产一些客观层面上的知识,例如查询指定类型数据库中所有的数据库表/schema的简单SQL,他还是每次给出了不一样的答案

Database&Schema的概念

今天开发业务设计到数据库和Schema的概念

由于之前一直使用的都是 MySQL,所以一直接触的都是数据库的概念

直到业务上用到了 Oracle PostgrelSQL 等关系型数据库之后才发现,其实 Database 和 Schema 的概念还是有很大的不同的

在以 MySQL 为代表的部分关系型数据库中,没有特别区分 Schema 和 Database 的概念,因此在 MySQL 中 Schema = Database

1
2
3
CREATE DATABASE TEST;
CREATE SCHEMA TEST;
#在 MySQL 中是等价语句

但是在 Oracle 等数据库中,Schema 是表的集合,Database 是 Schema 的集合

0713

给自己放了一天假

实际上是自己摸了一天鱼

0715

如何开发一个新的需求

在开发一个需求之前,首先需要先确认需求具体是什么,有哪些

确认需求之后就是根据产品的需求 在脑海中构建一套完整的业务流程

之后拆解每一块业务流程(于业务流程中涉及到的数据,考虑是否需要入库,如果需要入库就需要一套完整的 MVC 如果不需要入库,可能也需要内存对应的实体信息映射)想一想在这个流程中,需要用到那些 PO 实体?

确认了 PO 实体的大致方向,就可以进行字段的设计,字段的设计一般不太可能一蹴而就,需要反复的修改和更新,需要保持一定的耐心;同时字段设计的法则可以遵循以下的一些技巧:

  • 产品原型中数据相关的查询条件(往往就是要设计一个字段)
  • 表单填写的选项卡,维度

之后基于 PO 设计 MVC 三层代码,核心的实现和开发都是在 Service 层进行

0716

才搞懂JDBC

最近业务上需求和 Metadata 相关,有一说一知道今天才算了解到了什么是 JDBC 相关的一些知识

之前只是浅浅了解了一下,后面也就直接用框架了,没有再手写原生的 JDBC Connection 这些,今天才发现有些时候一些定制的需求还是不能太依赖框架,手写原生的JDBC之后封装,在管理维护上可能更为高效

在 JDBC 提供的各个接口中,各大数据库驱动都需要针对这个接口进行实现,提供对应数据源的信息,接口也定义了很多获取元数据的规范,这才是真正的面向接口编程

Java中JDBC的超详细总结

使用Map进行字段的封装

我们在开发 Service 的时候往往会需要返回多个字段信息,这种场景一般我们可以封装为特定的实体类,当然也可以直接返回 Map<String,String> 的方式来处理,其中key是字段名,value是字段值,之后在上游通过 Jackson 等库来解析转换为实体类

虽然个人不是很爱用这样的方式,更多的时候还是返回实体字段信息,但是在实际项目中也还是会出现,积累一下

0717

唯一不用加班的一天,回家爽爽摸鱼了属于是

0718

被接口文档单防

写 DTO 的时候一定要记得第一步就随手加上 @Data 注解提供 Get 方法

因为框架会调用对应的 get set 方法进行字段解析,如果没有 get set 方法,那么反映在接口文档中,就是显示不出正确的请求参数字段

0722

记得写 @Transactional 注解

0723

Docker部署MySQL8

本地装过一个 5.5的,环境不是很干净,尝试直接二进制文件部署,但是由于卸载残留等一些历史原因,失败了,所以急了直接跑容器

1
docker run --name mysql8 -e MYSQL_ROOT_PASSWORD=1 -e MYSQL_ALLOW_EMPTY_PASSWORD=false -e MYSQL_USER=test -e MYSQL_PASSWORD=1 -e MYSQL_DATABASE=test-db -v /挂载本地的数据目录:/var/lib/mysql -p 3306:3306 -d mysql:镜像tag

使用这样的方式可以快速拉起一个干净的 MySQL 同时映射到宿主主机和应用进行连接

Docker部署Redis单点+SpringBoot最佳实践

项目需要用到 Redis 来做数据缓存,减少 DB 频繁的读取压力

直接和 MySQL 一样本地拉一个容器

1
docker run --name ficp_redis -v c:/Users/28459/Desktop/PDS/redis_docker_data:/data -p 6379:6379 -d redis:latest

之后通过 Another Redis Desktop Manager 客户端可以直接连接

  • SpringBoot 整合 Redis 开发应用的最佳实践

SQL注入问题

回顾一下之前学习的 SQL 注入问题,其原理就是将 SQL 的查询条件参数以接口的方式暴露给客户端,由客户端程序进行编写之后在服务端进行 SQL 的拼接,可能会出现脏 SQL 的现象,例如:

1
select * from user where id = xxx;

这里的 xxx 我们交给用户进行填写,以前端参数传递

但是这只是一种理想的状态,保证了用户一定会传递合法的参数,但是如果用户传递的参数是 xxx and 1 = 1 最终执行的 SQL 就会是如下的情况

1
select * from user where id = xxx and 1 = 1;

目前各大框架也都针对 SQL 注入进行了处理,例如经典的 JDBC 就提供了 PreparedStatement 接口来实现 SQL 注入的预防

  • SQL注入的其他举例?
  • PreparedStatement 如何预防SQL注入?

SpringBean 注入方式

今天写代码的时候,由于需要注入 Redis 的客户端实例 RedisTemplate

然后项目之前已经有了一个 Bean 的注入,一时之间没有发现这是 Bean 的注入方式,只能说 @AutoWired 和 CRUD 注解类害人不浅

  • 构造器注入
  • @Bean 方法名注入 bean 对象

0724

JDBC API

0725

QueryDSL+SpringDataJPA 动态参数传递+模糊查询

今天有个需求是前端动态传递参数并且后端进行模糊查询

这给我搞蒙了,本身对 JPA 就不是很熟悉,模糊查询确实直接在 Repository 中用 Like 关键字定义方法名称就能实现全自动查询

但是动态参数传递确实是第一次在 JPA 遇到,以前都从来没用过,整理了一下内容:

首先是在 Repository 位置继承 QuerydslPredicateExecutor 接口

1
public interface MetadataRepository extends JpaRepository<MetadataPO, Long>,QuerydslPredicateExecutor<MetadataPO>{}

之后在上游的 Service 方法中,对参数存在与否进行判断拼接,之后将拼接的对象转换为 Predicate 类型的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Override
public Page<MetadataPO> queryPageByDatabaseAndTableNameAndGroupId(String databaseName, String tableName, Long groupId, Pageable pageable) {
QMetadataPO po = QMetadataPO.metadataPO;
BooleanBuilder builder = new BooleanBuilder();
if (tableName != null && !tableName.isEmpty()){
//对模糊查询的表名下划线进行转义
if (tableName.contains("_")){
tableName = tableName.replaceAll("_", "\\_");
}
builder.and(po.tableName.like("%" + tableName + "%"));
}
if (databaseName != null && !databaseName.isEmpty()){
builder.and(po.databaseName.eq(databaseName));
}
if (groupId != null){
builder.and(po.groupIds.contains(groupId));
}
//这里会直接调用传递 Predicate 参数
return metadataRepository.findAll(builder, pageable);
}

软件工程专业的怎么能不学电工知识呢

心血来潮想把焊接知识学习一下

一直想自己动手把 x360 做一个 RHG3.0 的 mod ,但是苦于不会焊接一直没办法做

同时 Switch 的 modchip 也已经比较成熟,生态和价格都已经相对友好

整合抽取了油管的 Soldering Tutorial 精华部分切片

后续可以考虑出一个文章记录


技术日记
http://example.com/2024/07/01/技术日记/
作者
Noctis64
发布于
2024年7月1日
许可协议