代码的艺术

编程 OS小编 发表了文章 0 个评论 164 次浏览 2022-05-18 14:46 来自相关话题

作者简介:章淼,章博士,清华大学计算机博士,百度云前端技术负责人,百度 Golang & Python 技术委员会成员。 笔记对比Google ...查看全部

作者简介:章淼,章博士,清华大学计算机博士,百度云前端技术负责人,百度 Golang & Python 技术委员会成员。


笔记

对比Google的工程师,国内的工程师写代码的占用时间显然过多了,而不太注重提前设计 ;Google 工程师们在开始实现某一模块或功能时,会事先在代码库中搜索是否已经有可重用的代码,并且代码库中的代码具有完整的注释和文档。


提前设计的重要性

尽可能地提前完成两个文档


  • 需求分析文档
  • 系统设计文档

原因:在未启动实现细节代码之前构思设计时发现问题的修改,对比后期真正已经开始Coding的时候,对比发现问题进行修改,成本要低很多。文档一般只写主要逻辑,而代码涉及更多细节。


笔者备注:但这不是绝对的,修改是正常的,不要惧怕修改,反复尝试积累经验。


  • 需求分析文档:主要是在定义黑盒状态,描述外在,描述WHAT要做什么?
  • 系统设计文档:主要实在定义白盒状态,描述内在,描述HOW怎么做?

两者要有区分,不要混淆 ,也不要混在一起写!


需求分析文档的误区:
不要过早提前构想实现细节,我们的大脑会下意识地在我们构想如何实现时遇到的各种难题,而将原本的需求分析的思考挂起;举例:导弹 vs 炸弹,两者都有摧毁目标的能力,但是很明显导弹的价值更高,重要的是制导的功能,而不是爆炸本身。

系统设计文档的误区:
主要要写定义系统的架构、模块、接口、数据、关键算法、设计思路等等得过程记录。

系统架构要写什么以及方法

概念、模型、视图等等。


  • 静:系统静态的样子,功能模块如何划分等
  • 动:系统运转起来,各模块联动起来的样子
  • 细:不同角度,不同层次去描述
  • 每一个组件(模块、函数)保证单一性, Single purpose. 只做一件事!
  • 轻耦合,低内聚(避免全局变量(多处操作难以控制))
  • 当前系统设计所受到的约束(当前设计的瓶颈在哪?比如网络、吞吐量、占用 CPU 或文件位置资源等)
  • 需求分析是系统设计的来源
  • 模型和抽象的思维能力很重要(涉及概念:模型、数据结构、算法等等)

设计接口(Interface)要注意什么?

  • 接口定义系统外在的功能
  • 接口定义当前系统与外部系统之间的关系

接口Interface定义了系统对外的接口,往往比系统实现内部细节代码更重要,不要过于草率,因为一旦定义了接口,提供出去给调用方使用,想修改就太难了。所以设计接口有重要原则,站在使用者的角度考虑问题!


两点细节:


  • 向前兼容(尽量不要接口已升级,老接口全不能用,那就不是好的接口设计)
  • 使用方便(让调用者可以一目了然知道接口的作用,简化传参,说明返回值等等)

如何写代码?

代码是一种表达的方式。是写给人看的,要有编程规范
拥有编程规范的理想状态:

  1. 看别人代码就像看自己代码一样易懂;
  2. 看代码主要看逻辑,不要过多注重细节;
  3. 代码尽可能地不要让人去多想。

Don’t make me think!


Moudle模块

紧内聚,低耦合。单一功能。反例,定义一个 utils.py 内部包含诸多方法,不易懂。


模块一般可以分为两类:


  • 数据类的模块(1. 主要完成对数据的封装; 2. 对外提供的数据接口)
  • 过程类的模块(1. 不要包含数据,可以是调用数据类的模块或者调用其他过程类模块; 2. 具备操作性质的模块)

模块的重要性:


  1. 降低维护成本;
  2. 更好地复用

Class类和Function函数

两者是不同的模型,各自有各自适用的范围。


推荐方法: 和类的成员无关的函数,尽量独立出去单独一个函数,不建议作为类的成员函数。


面向对象思想的讨论:多态和继承,需要谨慎适用,作为Python的工程师,不太推崇Java中继承和多态,因为系统是逐渐长起来的,并不是从一开始就是一个成熟的样子,所以很难凭空去设计一个继承的关系。


模块的构成

文件头(注释)


  • 模块的说明,简要功能
  • 修改历史(时间、修改人,修改的内容)
  • 其他特殊细节的说明

函数(重要性仅次于模块)


  • 描述功能
  • 传入参数的描述(含义、类型、限制条件等等)
  • 返回值得描述(有足够明确的语义说明)


    逻辑判断型 check is XXX
    操作型(成功 or 失败)
    数据获取型(状态 + 数据)

  • 异常如何处理(是抛出?还是内部catch?要明确)


  • 明确单入口和单出口(多线程开发时尤为重要)

函数要尽可能的规模小,足够短(BUG 往往出现在非常长的一个函数里)


代码块的分段也很重要,分段背后是划分和逻辑表达。


代码是一种表达能力的体现,也算是文科的范畴! 注释不是补出来的!


命名的重要性:要准确、易懂、可读性强,尽量做到 望名生义 。


互联网时代的系统是运营出来的。


可检测性也是尤其重要的。(埋点、监控等等)


没有数据的收集,等于系统没有上线。


监控不单单只有传统意义上的内存、CPU、网络、崩溃率的监控,还应有线上真实数据监控,需要有足够多的状态记录。


日志是很有限的一种监控手段,并且采集日志也是一种资源耗费。推荐的手段:可以使用埋点,对外提供接口,有单独的系统调用接口进行有针对性的采集。


修身

好的程序员,与工作年限无关,与学历无关


学习-思考-实践

学习:主观意愿地学习,途径也有很多,例如书籍、开源代码、社区。忌讳夜郎自大、井底之蛙。注重培养自己学习吸收的能力,多读多看但是数量不是最终目的。


Stay Hungry, Stay Foolish. – Steve Jobs


思考:学习需要经过思考,形成自己的思维。


实践:《卓有成效的时间管理者 - 德鲁克》推荐阅读


知识-方法-精神

知识过时会非常快!


方法:分析问题、解决问题的能力尤其重要(定义问题、识别问题、定义关键问题)


精神:决定型,要做就要坚持做


前进的道路上不能永远都是鲜花和掌声。


基础乃治学之根本。


数据结构、软件工程、逻辑思维能力、研究能力,需要5-8年时间磨炼。

kvm虚拟机启动报错Unable to find security driver for model selinux

运维 OS小编 发表了文章 0 个评论 189 次浏览 2022-05-17 15:46 来自相关话题

好久没用kvm虚拟话了,之前有台物理机配置比较高,就借助kvm虚拟化技术虚拟了几台虚拟机做实验完,但是今天启动报如下错误: [root@kvm-labs kvm]# virsh start centos7-lab ...查看全部

好久没用kvm虚拟话了,之前有台物理机配置比较高,就借助kvm虚拟化技术虚拟了几台虚拟机做实验完,但是今天启动报如下错误:


[root@kvm-labs kvm]# virsh start centos7-lab-node1
error: Failed to start domain centos7-lab-node1
error: unsupported configuration: Unable to find security driver for model selinux

根据错误提示,怀疑是系统selinux的问题,但是发现selinux是disabled,难道要强制用selinux,不合理啊。重新梳理逻辑,kvm虚拟机是可被定义的,是不是定义的配置文件中有selinux相关定义,那是不是可以去掉,经过实验还真ok,解决步骤如下。


1. 进入虚拟机配置文件目录

cd /etc/libvirt/qemu/
# 如果你构建环境修改过默认路径,根据实际情况进入

2. 编辑虚拟机配置文件

vim  centos7-lab-node1.xml

.....................
<input type='tablet' bus='usb'>
<address type='usb' bus='0' port='1'/>
</input>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
<listen type='address' address='0.0.0.0'/>
</graphics>
<video>
<model type='cirrus' vram='16384' heads='1' primary='yes'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
<rng model='virtio'>
<backend model='random'>/dev/urandom</backend>
<address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
</rng>
</devices>
<seclabel type='dynamic' model='selinux' relabel='yes'/>
</domain>

如上,删除<seclabel type='dynamic' model='selinux' relabel='yes'/> , 然后保存退出。


3. 重新定义配置文件

virsh define ./centos7-lab-node1.xml

然后重新执行virsh start centos7-lab-node1 就可以了。


如果想迁移虚拟机的存储路径也可以关机,修改配置文件下的存储路径,并将.qcow2文件移动到相应的目录下即可.


<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/data/kvmdata/centos7-lab-node1.qcow2'/>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</disk>

修改完成后,然后重新定义配置文件,重启虚拟机即可。

Centos系统进入单用户修改root用户密码

运维 OS小编 发表了文章 0 个评论 151 次浏览 2022-05-16 17:15 来自相关话题

1. 重启系统,在选择进入系统界面按字母e2. 在r ...查看全部

1. 重启系统,在选择进入系统界面按字母e

2. 在rhgb前添加’rw’ ,在行末添加 ‘init=/bin/sh’ ,按 ‘Ctrl+x’ 进入系统

进入系统后,修改密码

echo "www.baidu.com | passwd --stdin root
touch /.autorelabel
exec /sbin/init

等待一会,点击回车,进入重启。

装了心脏支架不能做和磁检查吗?

回复

医疗健康 OS小编 发起了问题 1 人关注 0 个回复 204 次浏览 2022-05-13 17:07 来自相关话题

vscode编辑器如何选中代码整体移动

回复

编程 OS小编 发起了问题 1 人关注 0 个回复 220 次浏览 2022-05-10 09:59 来自相关话题

吃黑芝麻能预防脱发吗?

回复

医疗健康 OS小编 回复了问题 1 人关注 1 个回复 229 次浏览 2022-05-08 11:27 来自相关话题

网页内容不允许复制怎么办?

运维 空心菜 回复了问题 2 人关注 1 个回复 211 次浏览 2022-04-24 17:15 来自相关话题

MySQL的三种复制模式

数据库 koyo 发表了文章 0 个评论 724 次浏览 2021-12-10 00:04 来自相关话题

MySQL支持的三种复制模式分别为: asynchronous 异步复制fully synchronous 全同步复制semi synchronous 半同步复制 ...查看全部

MySQL支持的三种复制模式分别为:


  1. asynchronous 异步复制
  2. fully synchronous 全同步复制
  3. semi synchronous 半同步复制

异步复制 (asynchronous replication)

原理:在异步复制中,master写数据到binlog且sync,slave request binlog后写入relay-log并flush disk
优点:复制的性能最好
缺点: master挂掉后,slave可能会丢失事务
代表:MySQL原生的复制

全同步复制 (fully synchronous replication)

原理:在全同步复制中,master写数据到binlog且sync,所有slave request binlog后写入relay-log并flush disk,并且回放完日志且commit
优点:数据不会丢失
缺点:会阻塞master session,性能太差,非常依赖网络
代表:MySQL Cluster

半同步复制 (semi synchronous replication)

1. 普通的半同步复制

原理: 在半同步复制中,master写数据到binlog且sync,且commit,然后一直等待ACK。当至少一个slave request bilog后写入到relay-log并flush disk,就返回ack(不需要回放完日志)
优点:会有数据丢失风险(低)
缺点:会阻塞master session,性能差,非常依赖网络,
代表:after commit, 原生的半同步



重点:由于master是在三段提交的最后commit阶段完成后才等待,所以master的其他session是可以看到这个提交事务的,所以这时候master上的数据和slave不一致,master crash后,slave数据丢失



2. 增强版的半同步复制(lossless replication)

原理: 在半同步复制中,master写数据到binlog且sync,然后一直等待ACK. 当至少一个slave request bilog后写入到relay-log并flush disk,就返回ack(不需要回放完日志)
优点:数据零丢失(前提是让其一直是lossless replication),性能好
缺点:会阻塞master session,非常依赖网络
代表:after sync, 原生的半同步



重点:由于master是在三段提交的第二阶段sync binlog完成后才等待, 所以master的其他session是看不见这个提交事务的,所以这时候master上的数据和slave一致,master crash后,slave没有丢失数据



重要参数:
































参数 评论 默认值 推荐值 是否动态
rpl_semi_sync_master_wait_for_slave_count 至少有N个slave接收到日志 1 1 dynamic
rpl_semi_sync_master_wait_point 等待的point AFTER_SYNC AFTER_SYNC dynamic
rpl_semi_sync_master_timeout 切换复制的timeout 1000(10s) 1000 (1s) dynamic
rpl_semi_sync_master_enabled 是否开启半同步 OFF ON dynamic
rpl_semi_sync_slave_enabled 是否开启半同步 OFF ON dynamic

如何开启lossless replication:


########semi sync replication settings########
plugin_dir=/usr/local/mysql/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 1000

实践是检验真理的唯一标准

如何检验上述after_syncafter_commit, 如何检验上述原理的正确性。


InnoDB commit: 三阶段提交过程
A阶段: wite prepare log 写入Xid
B阶段: write binlog
C阶段: write commit log

测试点:master上当一个事务Waiting for semi-sync ACK from slave的时候,后来的事务是在A,B,C哪个阶段卡住呢?


0,RC模式

1. semi-sync C阶段等待

假设设置time-out=100000s,当事务一提交了一个大事务,在write commit log(C阶段)时候等待,
那么第二个事务在敲commit命令的时候,是卡在哪个阶段呢?是卡在 wite prepare log(A阶段)?还是write binlog(B阶段)?还是write commit log(C阶段)

测试:semi-sync vs loss-less semi-sync

【semi-sync】 C阶段等待
0, 开启事务1,然后在slave上执行stop slave,制造timeout的情况,让其阻塞。(Waiting for semi-sync ACK from slave)
1,在开启一个事务2,事务2插入一条特殊记录(XXXXX)。 (Waiting for semi-sync ACK from slave)
2,在开启一个事务3。
2.1,测试案例:这个时候,kill -9 mysqld,造成人为的mysql crash
3,假设卡在A阶段,那么事务3,肯定是看不到事务1,2写入的记录(XXXXX),且重启mysql后,事务2不会提交。
4,假设卡在C阶段,那么事务3,肯定是可以看见事务1,2写入的记录(XXXXX)。

经过测试:
1,是卡在C阶段,也就是说事务3是可以看见事务1,事务2的。
2,MySQL crash重启后,事务1,事务2的dml都已经提交成功,说明不是卡在A阶段

【loss-less semi-sync】B阶段等待

0, 开启事务1,然后在slave上执行stop slave,制造timeout的情况,让其阻塞。(Waiting for semi-sync ACK from slave)
1,在开启一个事务2,事务2插入一条特殊记录(XXXXX)。(Waiting for semi-sync ACK from slave)
2,在开启一个事务3
3,假设卡在A阶段,那么事务3,肯定是看不到事务1,2写入的记录(XXXXX),且重启mysql后,事务2不会提交。。
4,假设卡在B阶段,那么事务3,肯定是可以看见事务1,2写入的记录(XXXXX),且重启mysql后,事务1,2都会提交。。
5, 假设卡在C阶段,那么事务3,肯定是可以看见事务3写入的记录(XXXXX)。

经过测试:
1,是卡在B阶段,也就是说事务3,既看不见事务1的提交内容,也看不见事务2的提交内容,且重启mysql后,事务1,2都已经提交。。
2,MySQL crash重启后,事务1,事务2的dml都已经提交成功,说明不是卡在A阶段。

性能
semi-sync vs lossless semi-sync 的性能对比


根据以上的测试,可以得知,lossless只卡在B阶段,普通的semi-sync是卡在C阶段。
lossless的性能远远好于普通的semi-sync,即(after_sync 优于 after_commit)
因为lossless 卡在B阶段的时候可以堆积事务,可以在C阶段进行group commit。
普通的semi-sync,卡在C阶段,事务都已经commit了,并没有堆积的过程。


CAP理论:



一致性【C】
可用性【A】
分区容忍性【P】
理论:CAP 三者不可兼得,必须要牺牲一个


分区,是一定存在的,不是你想不要就不要的。所以,这里只剩下两种组合


CP 牺牲可用性



这种做法,就是保留强一致性,牺牲可用性
案例:可以将rpl_semi_sync_master_timeout设置成一个无限大的值,比如:100天,那么master和slave就强一致了,但是可用性就大打折扣


AP 牺牲一致性



这种做法,就是保留高可用性,牺牲一致性
案例:比如原生的异步复制就是这样咯。可以快速做到切换,但是一致性就没有保障


阅读分享:https://henduan.com/FJHU5

什么是Redis,Redis有什么特点和优势?

数据库 OS小编 回复了问题 2 人关注 1 个回复 785 次浏览 2021-12-01 13:09 来自相关话题

安可产业名录和国产化替代

运维 chris 发表了文章 0 个评论 6594 次浏览 2021-11-30 15:52 来自相关话题

关于国家信息化安全可靠工程随着信息安全问题日益突出,信息安全已上升至国家战略,自主可控,国产化替代已成为历史趋势。2019年开始我国信息、网安领域企业逐渐发力“安全可靠工程”,安全可靠工程战略意义在于证明我国具有安全可靠关键系统、关键应 ...查看全部

关于国家信息化安全可靠工程

随着信息安全问题日益突出,信息安全已上升至国家战略,自主可控,国产化替代已成为历史趋势。2019年开始我国信息、网安领域企业逐渐发力“安全可靠工程”,安全可靠工程战略意义在于证明我国具有安全可靠关键系统、关键应用及关键软硬件产品的研发集成能力,能够初步实现对国外信息技术产品的全方位替代,在新的历史起点上构建起网络安全的“铜墙铁壁”。在党政办公及国家重要信息系统推进国产化替代,实现安全可靠、自主可控,保障国家信息安全的工作已全面展开。

安可名录

安全可靠技术和产业联盟主要成员单位包括联盟理事和联盟会员两大类。
其中联盟理事(19家)又分为:集成厂商(10家)、测试厂商(4家)、互联网厂商(3家)和高等院校(2家)四大类。

集成厂商(10家)包括:
华宇软件、神州航天软件、东华软件、东软集团、航天信息、浪潮软件集团、神州信息、太极股份、同方股份、中国软件

测试机构(4家)包括:
国家工业信息安全发展研究中心、中国电子技术标准化研究院、工业和信息化部电子第五研究所、中国电子信息产业发展研究院

互联网厂商(3家)包括:
阿里云、金山软件、华为技术

高等院校(2家)包括:
北京航空航天大学、北京理工大学

联盟会员则包含:芯片厂商(7家)、集成厂商(12家)、整机厂商(8家)、操作系统厂商(9家)、数据库厂商(6家)、中间件厂商(3家)、流版签厂商(7家)、外设固件厂商(3家)、安全厂商(6家)、网络厂商(3家)、互联网厂商(2家)、存储厂商(5家)和应用软件厂商(2家)共十二大类。


芯片厂商(7家)包括:
上海兆芯(X86)、东土军悦(交换机芯片、东土科技)、国科微(安防、存储、物联网芯片)、盛科网络(交换机芯片、中国电子、振华科技)、天津飞腾(ARM、中国长城、振华科技)、上海高性能集成电路设计中心(Alpha、申威)、龙芯中科(MIPS)

集成厂商(12家)包括:
百得科技、华胜天成、中软信息(中国软件)、广东省信息工程公司、中科软、南威软件、太极信息(太极股份)、烽火信息(烽火通信)、万达信息、中软系统(中国软件)、中科九洲、长城软件(中国软件)

整机厂商(8家)包括:
上海仪电智通、联想长风、华胜天成、长城科技(中国长城)、宝德网络、曙光信息(中科曙光)、百信信息、北京计算机技术及应用研究所(航天二院706所)

操作系统厂商(9家)包括:
中科方德(兆芯)、一铭软件、湖南麒麟信安(中国软件)、天津麒麟(中国软件)、思普投资(X86)、深之度、普华基础软件(中国电科)、航天国盛(航天科技)、中标软件(中国软件)

数据库厂商(6家)包括:
武汉达梦(中国软件)、神舟通用(航天科技)、人大金仓(太极股份)、南大通用、恒辉信达、瀚高基础软件

中间件厂商(3家)包括:
金蝶天燕中间件、东方通、中创软件

流版签厂商(7家)包括:
金格科技(电子签章)、方正国际软件(电子文档)、书生电子(启明星辰、安全文档)、数科网维(版式OFD)、航天福昕(文档OFD)、安证通(电子签章)、永中软件(office,办公软件)

外设固件厂商(3家)包括:
立思辰(文件管理)、中电科技(中国电子、BIOS等)、光电通信(传真机)

安全厂商(6家)包括:
星网锐捷(通信、安全)、中孚信息(安全保密)、安宁创新(邮件、消息)、中安网脉(密码、存储)、海泰方圆(密码、安全)、卫士通(密码、芯片、系统)

网络厂商(3家)包括:
紫光集团(从芯到云)、迈普通信(中国电子、网络设备)、仰联信通(交换机)

互联网厂商(2家)包括:
拓尔思、恒生电子

存储厂商(5家)包括:
滕凌科技(存储)、亚细亚智业(存储灾备)、同有科技(存储)、鲸鲨软件(存储)、鼎甲科技(中国电子、灾备)

应用软件厂商(2家)包括:
慧点科技(太极股份、管理软件)、华电园技术(办公自动化)

国产化软硬件资源

应用软件
监控国产数据库:达梦数据库、南大通用、人大金仓、神舟通用;

大数据产业下,对金融、电信、航空、制造等行业影响非常明显,其中国产数据库的作用被不断提升,担负起捍卫国家信息安全和技术的重任。
监控国产中间件:东方通、中创、金碟等中间件;

中间件一直是基础软硬件发展中不可缺少的一环,占居重要的地位。2018年以来本土中间件加快进入电信、金融、政府等行业,由东方通作为开拓者和领导者,中创、宝兰德等追其后。


操作系统
监控中标麒麟、银河麒麟、深度科技、红旗、中兴新支点等操作系统;

在持续的贸易战背景下,由于我们受到了外国的管控,操作系统等核心技术一度面临被限制使用的局面,于是国产操作系统被推到了风口浪尖。


硬件资源
监控国产服务器:华为、曙光、H3C、联想、浪潮;
国产服务器发展已将近二十载,二十载潮起潮落,国产服务器已涌现出联想、曙光、浪潮、华为等一批民族品牌。现在国产服务器已抢占更多服务器市场份额。

监控国产存储设备:华为、曙光、H3C、同有、浪潮;


网络资源
监控国产网络设备:华为、H3C、仰联、TP-LINK、ZTE中兴、锐捷等;

监控国产安全设备:天融信、启明星辰、绿盟、网康、趋势科技、山石网科等;
中国最核心的网络安全设备大部分依赖于进口,不具有强大的防御与反击能力,安全问题依然严峻。单靠技术无法抑制网络安全事件增长。核心网络设备国产化是解决这一问题最好的办法。



应用环境
兼容国产数据库:达梦数据库、南大通用、人大金仓、神舟通用;

兼容国产中间件:东方通、中创、金碟等中间件;


硬件环境


兼容国产服务器:华为、曙光、H3C、联想、浪潮;
兼容国产 CPU:龙芯、飞腾、海思、鲲鹏、展讯通信;

系统环境
兼容国产操作系统:中标麒麟、银河麒麟、深度科技、红旗、中兴新支点;

更多话题 >>

热门话题

mac

2 个问题, 1 人关注

更多用户 >>

热门用户

koyo

14 个问题, 23 次赞同

OS小编

13 个问题, 4 次赞同

空心菜

152 个问题, 108 次赞同