2024年8月

在技术社区的快速变革中,园子似乎未能跟上时代的步伐。从.NET on Linux的尝试到对博客时代的执着,园子的决策似乎总是与市场趋势背道而驰。面对微信订阅号的崛起和移动流量的流失,园子显得反应迟缓,错失了转型的黄金时期。

园子在用户定位上的模糊不清,导致了产品策略的摇摆不定。开发者需要的是一个能够提供深度技术交流和资源共享的平台,而非简单的内容发布工具。园子是否真正理解了这一需求,值得我们深思。

品牌价值的不明确,使得园子在技术社区中的形象日渐模糊。在AI产品和stackoverflow等平台的冲击下,园子的看文章用户预期中的锐减,广告收入的减少,进一步凸显了园子在品牌建设上的不足。

投资策略的短视,如众包平台的推出,不仅未能吸引投资者的想象力,反而暴露了园子在创新能力上的不足。在技术日新月异的今天,园子需要更加前瞻性的投资策略,以适应不断变化的市场环境。

为了实现盈亏平衡,园子必须痛定思痛,关闭那些不再符合市场需求的产品和功能。这不仅是一次自我革新的过程,更是园子重新定位和重塑品牌的机遇。

园子的困境,是每一个技术社区都需要面对的挑战。只有通过深刻的自我批判和不断的自我革新,园子才能在技术社区的浪潮中找到自己的生存之道。让我们期待园子能够以更加坚定和明智的步伐,走出困境,迎接新的挑战。


园子活下去最重要的是盈亏平衡

那么园子关闭哪些产品 和功能 才能保持盈亏平衡 活下去 从0开始
大家觉得园子怎么才能活下去

前言

电源供电电路设计很重要,为了更好的给对硬件设计有需求的人,特意将电源设计的基础过程描述出来。
紧接前一篇12V转5V的,本篇设计常用的12V转3.3V电路,不常用的12V转4V电路。


12V转3.3V电路


步骤一:应用典型电路


(依据底板和典型电路得差别,电感和电容在3.3~5V范围内,我们可以不调整)


步骤二:调整输出电压

TPS54331 器件的输出电压可从外部通过电阻分压器网络进行调节。

3.3V = 0.8V x ( R5/R6 + 1)
R5/R6 + 1 = 3.3/0.8
R5/R6 = 4.125 - 1
R5/R6 = 3.125

由于阻值选择高精度1%的电阻,然后最好是标准的,可查看《
硬件实用技巧:电阻精度和常用阻值表
》,选择阻值R6为20KΩ,R5为105KΩ。
典型电路:10.2/3.14 = 3.14,试了几个确实找不到这么接近的比值了,就这个了。
在这里插入图片描述


12V转4V电路


步骤一:应用典型电路

在这里插入图片描述


步骤二:调整输出电压

TPS54331 器件的输出电压可从外部通过电阻分压器网络进行调节。
在这里插入图片描述

4V = 0.8V x ( R5/R6 + 1)
R5/R6 + 1 = 4/0.8
R5/R6 = 5 - 1
R5/R6 = 4

由于阻值选择高精度1%的电阻,然后最好是标准的,可查看《硬件实用技巧:电阻精度和常用阻值表》,选择阻值R6为9.1KΩ,R5为36.4KΩ。

36.5 KΩ/9.1 KΩ=4.010
39 KΩ/9.76 KΩ=3.995
80.6 KΩ/20 KΩ=4.030

在这里插入图片描述

(依据底板和典型电路得差别,电感和电容在3.3~5V范围内,我们可以不调整)。


对原理图进行自动标注编号

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

都有编号了。


输出原理图

在这里插入图片描述

进行审核。

大家好,我是
晓凡。

有很多小伙伴尤其是在校大学生或者想转软件开发的小伙伴,经常会问:准备找工作了,没有项目经验怎么办呢?

这时候上网找开源项目学习,就是一个获取项目经验比较靠谱的途径。

这时候又有小伙伴问了,去哪找开源项目呢?

当然是全球最大的的
同性交友网站
GitHub
上找了。

这时候又有小伙伴问了,我的英文不好,怎么才能在
GitHub
上找到适合自己的开源项目呢?

那么今天推荐的这个开源项目
GitHub-Chinese-Top-Charts
或许能帮助到你

一、项目简介


项目名称

GitHub-Chinese-Top-Charts
又称
GitHub
中文排行榜


项目地址

https://github.com/GrowingGit/GitHub-Chinese-Top-Charts

GitHub中文排行榜


项目stars数

项目目前已有:
96.5k


更新频率

从上面截图可以看到,最近更新时间是6小时前,更新频率非常的频繁


项目宗旨

「帮助你发现优秀中文项目,可以无语言障碍地、更高效地吸收优秀经验成果」

各语言分设「软件 | 资料」榜单,精准定位中文好项目。

通过项目,可以各取所需,提高学习效率,找到适合自己的开源项目

二、项目亮点

项目一共包含
3个大榜单
,每个榜单下面都包含
软件类

资料类

项目还包含了各种编程语言,按语言受欢迎程度有高到低排序

3大榜单

2.1 中文总排行榜

  • 筛选出有中文文档的项目进行排名,帮助大家更低门槛探索优秀开源项目,打破语言障碍;
  • 中文项目既包含国产好项目,也包含国外优质的含中文文档的项目;
  • 评选逻辑是保持活跃+总星数;

2.2 中文增速榜

  • 帮助大家发现增速较快的项目,优秀不止于老项目;
  • 评选逻辑是保持活跃+日均涨星数;

2.3 中文新秀榜

  • 帮助大家发现近一年的潜力新项目,后起之秀就在这里;
  • 评选逻辑是保持活跃+近一年内创建的较高星项目;

三、使用示例

3.1 如何找优秀的Java开源项目?

① 在中文总榜中找到软件类下的Java

Java软件类

②找到J优秀的Java项目

进入链接之后,我们就可以看到按stars数排名的Java项目。

表中如下图所示包含了仓库地址,项目简介,Stars数,最近更新时间。

像下面截图中所示,第一个就是一个非常不错的电商项目

image-20240801215633127

3.2 如何找到优秀的Java学习资料

① 在中文总榜中找到资料类下的Java

image-20240801220114742

②找到优秀的Java资料库

这时候我们熟悉的
JavaGuide
项目就出来了,根据这个排名,我们还可以找到更加优质的学习资料

Java资料库

以上,由于文章篇幅原因,只以Java编程语言为例做筛选,其他语言按照类似操作即可。

四、兄弟项目

当你觉得中文项目已通关,作者也提供了兄弟项目
GitHub
英文排行榜

项目地址:

https://github.com/GrowingGit/GitHub-English-Top-Charts

英文排行榜地址

和中文排行榜一样,
GitHub
英文排行榜

也有3个榜单

三个榜单

五、番外

以上各小节说了怎么根据
GitHub-Chinese-Top-Charts
来找到合适的开源项目。

这一小节,虽然有了这个开源项目,我们也得学一学
GitHub上
搜索优秀项目的小技巧。

  1. 使用关键词
    :首先,确定你想要搜索的项目类型或功能,使用相关的关键词进行搜索。例如,如果你想要搜索关于机器学习的库,可以使用"machine learning library"作为关键词。
  2. 利用搜索过滤器

    • 语言
      :使用
      language:java
      来筛选特定编程语言的项目。
    • 星星数
      :使用
      stars:>3000
      来找到至少有1000个星星的项目,这通常意味着项目比较受欢迎。
    • 创建时间
      :使用
      created:>YYYY-MM-DD
      来找到特定日期之后创建的项目。
    • 更新时间
      :使用
      pushed:>YYYY-MM-DD
      来找到最近有更新的项目,这表明项目还在积极维护。
  3. 排序选项


    • 最佳匹配
      排序:
      GitHub
      默认的排序方式,综合了项目的各种因素。

    • 星星数
      排序:
      sort:stars
      ,找到最受欢迎的项目。

    • 最近更新
      排序:
      sort:updated
      ,找到最近有活跃开发的项目。
  4. 查看趋势
    :访问https://github.com/trending页面,这里展示了当前最火的项目,按照语言和时间进行分类。
  5. 利用
    GitHub Explore


    https://github.com/explore,这里
    GitHub
    会推荐一些高质量的项目和开发者。
  6. 阅读
    README
    文件

    :在搜索结果中,快速浏览项目的
    README
    文件,了解项目的功能、用途和如何开始使用。

本期内容到这儿就结束了,希望您能找到适合自己的开源项目,提升项目经验,最终成功上岸。

我们下期再见 ヾ(•ω•`)o (●'◡'●)

jpa+querydsl的平替国产easy-query最好用的orm

一款国产最强java orm,完美支持可控强类型dsl,外加完美支持对象模型筛选拉取的orm,拥有非常智能的include(s)一对多、一对一、多对多、多对一实现的orm

地址github:
https://github.com/dromara/easy-query

地址gitee:
https://gitee.com/dromara/easy-query

文档地址:
http://www.easy-query.com/easy-query-doc/

一款拥有高度抽象屏蔽各大数据库方言的orm,让你的换库如鱼得水非常方便,集成实现各种数据库方言的使用,让你轻松应对各种需求,并且在对象模型上让你可以省去大把时间在多对多之间来回筛选

场景1

用户和角色,角色和菜单我们都知道这是最最最基础的一个场景,其中用户和角色是多对多,角色和菜单也是多对多

往往普通orm在演示的时候只会对当前表的属性进行筛选排序等操作,但是如果遇到查询主表筛选条件是子表那么大部分orm都是很麻烦的,想写出来往往是非常的费时费力并且还不支持动态条件

  • 筛选用户
  • 条件角色包含管理员的
 List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合里面有角色名称叫做管理员的
                    s.roles().any(role -> {
                        role.name().eq("管理员");
                    });
                }).toList();

什么你还嫌麻烦,那么如果你只有一个条件可以对roles进行展开来断言

当且仅当
一(多)对多
的时候那么关联模型将是集合的时候如果希望断言是否存在集合内的单一属性条件判断可以通过
flatElement
展开属性直接判断

        List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合里面有角色名称叫做管理员的
                    s.roles().flatElement().name().eq("管理员");
                }).toList();

我们来看看具体执行的sql

-- 第1条sql数据
SELECT
    t.`id`,
    t.`company_id`,
    t.`name`,
    t.`age`,
    t.`create_time` 
FROM
    `t_user` t 
WHERE
    EXISTS (
        SELECT
            1 
        FROM
            `t_role` t1 
        WHERE
            EXISTS (
                SELECT
                    1 
                FROM
                    `t_user_role` t2 
                WHERE
                    t2.`role_id` = t1.`id` 
                    AND t2.`user_id` = t.`id` LIMIT 1
            ) 
            AND t1.`name` = '管理员' LIMIT 1
        )

如果你要执行这个sql还要动态条件那么真的非常让人绝望
有人说如何做动态条件呢

   List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合里面有角色名称叫做管理员的
                   if(false){
                       s.roles().any(role -> {
                           role.name().eq("管理员");
                       });
                   }
                }).toList();

是的你没看错就这么简简单单的一个条件就可以让其支持动态多对多筛选,那么如果这个条件是false那么生成的sql将是怎么样的呢

SELECT `id`,`company_id`,`name`,`age`,`create_time` FROM `t_user`

是不是被easy-query这么智能的条件处理惊讶到了,如果你需要手写那么将会是灾难何况还有逻辑删除和各种拦截器

那么我们再来看看下一个场景

场景2

用户和角色和菜单

分别是多对多 和多对多

  • 筛选用户
  • 条件是用户拥有/admin的菜单
  List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合里面的菜单是/admin
                    s.roles().any(role -> {
                        role.menus().any(menu->{
                            menu.route().eq("/admin");
                        });
                    });
                }).toList();

哇哦简直完美简洁,什么你觉得还是太复杂了那么我们再将其简化

      List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合里面的菜单是/admin
                    s.roles().flatElement().menus().any(menu->{
                        menu.route().eq("/admin");
                    });
                }).toList();


//上下两种都可以,因为我们没有对roles进行条件筛选
//所以可以直接通过两次flatElement来展开元素直接断言菜单


        List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合里面的菜单是/admin
                    s.roles().flatElement().menus().flatElement().route().eq("/admin");
                }).toList();

接下来我们再来看看生成的sql


-- 第1条sql数据
SELECT
    t.`id`,
    t.`company_id`,
    t.`name`,
    t.`age`,
    t.`create_time` 
FROM
    `t_user` t 
WHERE
    EXISTS (
        SELECT
            1 
        FROM
            `t_role` t1 
        WHERE
            EXISTS (
                SELECT
                    1 
                FROM
                    `t_user_role` t2 
                WHERE
                    t2.`role_id` = t1.`id` 
                    AND t2.`user_id` = t.`id` LIMIT 1
            ) 
            AND EXISTS (
                SELECT
                    1 
                FROM
                    `t_menu` t3 
                WHERE
                    EXISTS (
                        SELECT
                            1 
                        FROM
                            `t_role_menu` t4 
                        WHERE
                            t4.`menu_id` = t3.`id` 
                            AND t4.`role_id` = t1.`id` LIMIT 1
                    ) 
                    AND t3.`route` = '/admin' LIMIT 1
                ) LIMIT 1
        )

我已经麻了如果没有orm简直不敢想

场景3

  • 查询用户
  • 条件是用户拥有的角色数量不少于3个的
        List<SysUser> managers = easyEntityQuery.queryable(SysUser.class)
                .where(s -> {
                    //筛选条件为角色集合的数量大于等于3个
                    s.roles().count().ge(3L);
                }).toList();

非常符合直觉
生成的sql呢是怎么样的


-- 第1条sql数据
SELECT
    t.`id`,
    t.`company_id`,
    t.`name`,
    t.`age`,
    t.`create_time` 
FROM
    `t_user` t 
WHERE
    (
        SELECT
            COUNT(*) 
        FROM
            `t_role` t1 
        WHERE
            EXISTS (
                SELECT
                    1 
                FROM
                    `t_user_role` t2 
                WHERE
                    t2.`role_id` = t1.`id` 
                    AND t2.`user_id` = t.`id` LIMIT 1
            )
        ) >= 3

场景4

  • 查询角色
  • 条件是角色关联的用户平均年龄是15岁或者姓金的至少有2位以上
List<SysRole> roles = easyEntityQuery.queryable(SysRole.class)
                .where(role -> {
                    role.or(()->{
                        role.users().avg(u->u.age()).ge(BigDecimal.valueOf(15));
                        role.users().where(u->u.name().likeMatchLeft("金")).count().ge(2L);
                    });
                }).toList();

让我们来看看生成的sql

-- 第1条sql数据
SELECT
    t.`id`,
    t.`name`,
    t.`create_time` 
FROM
    `t_role` t 
WHERE
    (
        IFNULL((SELECT
            AVG(t1.`age`) 
        FROM
            `t_user` t1 
        WHERE
            EXISTS (SELECT
                1 
            FROM
                `t_user_role` t2 
            WHERE
                t2.`user_id` = t1.`id` 
                AND t2.`role_id` = t.`id` LIMIT 1)),0) >= '15' 
        OR (
            SELECT
                COUNT(*) 
            FROM
                `t_user` t4 
            WHERE
                EXISTS (
                    SELECT
                        1 
                    FROM
                        `t_user_role` t5 
                    WHERE
                        t5.`user_id` = t4.`id` 
                        AND t5.`role_id` = t.`id` LIMIT 1
                ) 
                AND t4.`name` LIKE '金%'
            ) >= 2
    )

不要看这个sql这么复杂这可是多对多下的查询正常人压根没办法写这种sql

最后

这边展示了非常强大的OLTP查询模式,OLAP也是非常强大可以group+join,实现from (匿名sql) 也可以join (匿名sql)

一款具有强类型OLTP+OLAP的完美解决方案,并且完美支持mybatis系列的任意架构逐步构建迁移,不会产生任何冲突,因为easy-query本身就是零依赖,并且完全免费,完全开源(包括文档!!!包括文档!!!包括文档!!!)

我相信
easy-query
是一款可以完完全全打动您的ORM作品,也是全java唯一一款全sql替代性产品

前言

组合式 (Composition) API
的一大特点是“非常灵活”,但也因为非常灵活,每个开发都有自己的想法。加上项目的持续迭代导致我们的代码变得愈发混乱,最终到达无法维护的地步。本文是我这几年使用组合式API的一些经验总结,希望通过本文让你也能够写出
易维护

优雅

组合式API
代码。

欧阳写了一本开源电子书
vue3编译原理揭秘
,这本书初中级前端能看懂。完全免费,只求一个star。

选项式API

vue2的选项式API因为每个选项都有固定的书写位置(比如数据就放在
data
里面,方法就放在
methods
里面),所以我们只需要将代码放到对应的选项中就行了。

优点是因为已经固定了每个代码的书写位置,所有人写出来的代码风格都差不多。

缺点是当单个组件的逻辑复杂到一定程度时,代码就会显得特别笨重,非常不灵活。
option-api

随意的写组合式API

vue3推出了
组合式 (Composition) API
,他的主要特点就是非常灵活。解决了选项式API不够灵活的问题。但是灵活也是一把双刃剑,因为每个开发的编码水平不同。所以就出现了有的人使用组合式 (Composition) API写出来的代码非常漂亮和易维护,有的人写的代码确实很混乱和难易维护。

比如一个组件开始的时候还是规规矩矩的写,所有的
ref
响应式变量放在一块,所有的方法放在一块,所有的
computed
计算属性放在一块。

但是随着项目的不断迭代 ,或者干脆是换了一个人来维护。这时的代码可能就不是最开始那样清晰了,比如新加的代码不管是
ref

computed
还是方法都放到一起去了。如下图:
chao

只有
count1

count2
时,代码看着还挺整齐的。但是随着
count3
的代码加入后看着就比较凌乱了,后续如果再加
count4
的代码就会更加乱了。

有序的写组合式API

为了解决上面的问题,所以我们约定了一个代码规范。同一种API的代码全部写在一个地方,比如所有的
props
放在一块、所有的
emits
放在一块、所有的
computed
放在一块。并且这些模块的代码都按照约定的顺序去写,如下图:
sort

随着vue组件的代码增加,上面的方案又有新的问题了。

还是前面的那个例子比如有5个
count

ref
变量,对应的
computed

methods
也有5个。此时我们的vue组件代码量就很多了,比如此时我想看看
computed1

increment1
的逻辑是怎么样的。

因为
computed1

increment1
函数分别在文件的
computed

methods
的代码块处,
computed1

increment1
之间隔了几十行代码,看完
computed1
的代码再跳转去看
increment1
的代码就很痛苦。如下图:
long

这时有小伙伴会说,抽成
hooks
呗。这里有5个
count
,那么就抽5个
hooks
文件。像这样的代码。如下图:
hooks-file

一般来说抽取出来的
hooks
都是用来多个组件进行逻辑共享,但是我们这里抽取出来的
useCount
文件明显只有这个vue组件会用他。达不到逻辑共享的目的,所以单独将这些逻辑抽取成名为
useCount

hooks
文件又有点不合适。

最终解决方案

我们不如将前面的方案进行融合一下,抽取出多个
useCount
函数放在当前vue组件内,而不是抽成单个
hooks
文件。并且在多个
useCount
函数中我们还是按照前面约定的规范,按照顺序去写
ref
变量、
computed
、函数的代码。

最终得出的最佳实践如下图:
perfect

上面这种写法有几个优势:

  • 我们将每个
    count
    的逻辑都抽取成单独的
    useCount
    函数,并且这些函数都在当前vue文件中,没有将其抽取成
    hooks
    文件。如果哪天
    useCount1
    中的逻辑需要给其他组件使用,我们只需要新建一个
    useCount
    文件,然后直接将
    useCount1
    函数的代码移到新建的文件中就可以了。

  • 如果我们想查看
    doubleCount1

    increment1
    中的逻辑,只需要找到
    useCount1
    函数,关于
    count1
    相关的逻辑都在这个函数里面,无需像之前那样翻山越岭跨越几十行代码才能从
    doubleCount1
    的代码跳转到
    increment1
    的代码。

总结

本文介绍了使用
Composition API
的最佳实践,规则如下:

  • 首先约定了一个代码规范,
    Composition API
    按照约定的顺序进行书写(书写顺序可以按照公司代码规范适当调整)。并且同一种组合式API的代码全部写在一个地方,比如所有的
    props
    放在一块、所有的
    emits
    放在一块、所有的
    computed
    放在一块。

  • 如果逻辑能够多个组件复用就抽取成单独的
    hooks
    文件。

  • 如果逻辑不能给多个组件复用,就将逻辑抽取成
    useXXX
    函数,将
    useXXX
    函数的代码还是放到当前组件中。

    第一个好处是如果某天
    useXXX
    函数中的逻辑需要给其他组件复用,我们只需要将
    useXXX
    函数的代码移到新建的
    hooks
    文件中即可。

    第二个好处是我们想查看某个业务逻辑的代码,只需要在对应的
    useXXX
    函数中去找即可。无需在整个vue文件中翻山越岭从
    computed
    模块的代码跳转到
    function
    函数的代码。

关注公众号:【前端欧阳】,给自己一个进阶vue的机会

另外欧阳写了一本开源电子书
vue3编译原理揭秘
,这本书初中级前端能看懂。完全免费,只求一个star。