精华内容
下载资源
问答
  • 互联网的成功和端到端原则
    千次阅读
    2022-03-24 18:02:51

    本文很短,就几句话。

    互联网之所以发展迅速,得益于端到端原则:

    • 保持一个极简的核心,将复杂留在端。

    道理很简单。

    核心若不极简,互联网将无法适应变化。随着接入节点的增加,核心的负担将指数增加,互联网规模终将停滞。

    全文完。以下是后序。

    写在后面

    网络是分布式的,要实现一个网络功能时,需要选一个部署它的位置,换言之,是在转发节点实现还是在端节点实现。

    计算机技术的发展让端越发智能,各类应用的蓬勃是迟早的事,它们对网络的需求各自不一。

    以可靠传输为例,若在网络中心实现逐跳可靠传输,必然需要在每一跳记录状态,随着新节点的接入,状态记录将指数增长,转发节点终将不堪重负而崩溃。在中心实现其它需求,结果亦然。

    简言之,在中心实现网络需求,没有可扩展性,无法适应变化,而唯一不变的是变化本身。

    拥抱变化的取向迫使端到端的需求在端到端实现。否则,互联网甚至无法起步,更别提发展。

    就这一点足以确定互联网的架构,其余的都是结果。

    先看成本因素,遵循端到端原则是最划算的。

    网络核心实现的任何功能,其代价均是全局的。网络核心是所有通信必经之处,任何一个功能,均会对途径的所有数据包进行额外操作,哪怕改功能并不是所有应用必须的。无论该功能软硬件设施所需的金钱,还是额外操作所损耗的时间,都是净损耗。不划算。

    再看完备性,遵循端到端原则最完备。

    网络核心实现的所有功能,必须满足所有端到端需求的全集,但端到端需求是不断变化的,因此在任何时间点均不存在完备的全集。若实现一个子集,那么实现谁忽略谁将造成不公平。网络核心无法满足全集,又不能简化实现功能子集,端到端需求在端到端满足便是必然。

    最后看透明性,遵循端到端原则是保持端到端透明的唯一方式。

    网络核心实现的功能,必然涉及对数据包的写操作,比如逐跳的可靠性保证,数据包的目的地永远是下一跳,源则是当前节点,源和目标在网络传输路径上不断变化,端到端的源和目标不再保持。若将功能实现在端,对于应用而言,就好像网络根本不存在一样。因此,端到端原则保持了最佳的透明性。

    最终,网络核心只保留不得已而必须的传输功能,它极简,无状态,因此只能“尽力而为”,“逐跳传输”。无论是尽力而为还是逐跳传输,都是端到端原则的必然结果,现实中,这个核心就是IP协议。IP一点也不多,一点也不少,它是系着两个罐子的那根细绳子。

    简单说说TCP/IP分层。它也是端到端原则的结果。

    TCP/IP一开始并不是分层协议族,它是一个端到端的TCP协议,按照端到端的原则做了减法之后,IP协议分离了出来,这个分离来自于一个减法原则:“网关在搬移数据包时是否需要这个信息,若不需要,那这个信息就不该放入IP”。

    这个减法将TCP变成了一个双层协议,TCP/IP。所有使用TCP/IP的上层,便生成了TCP/IP协议族。

    IP是个极简协议,它只读(TTL字段只是一个增强),无状态,路由器只看目标地址即可完成转发。

    分层协议族的演化表明互联网不是设计规划出来的,而是进化出来的,这个和近乎完备的ISO/OSI完全不同。

    端到端原则的核心产物便是分布式路由了。

    极简的IP协议唯一特征是全局编址,互联网所有节点组成了一张图,每个节点由一个IP地址标识,所有节点通过与邻居交换信息执行分布式算法,每个节点均会生成一张路由表,节点依照这张路由表执行数据包转发,由于IP是无状态的,转发必然是逐跳的,每个节点均无全局信息,却能将数据包按照最短路径送达目标,大雅。

    端到端原则似乎是绝对正确的,事实果真如此吗?

    回顾从阿帕网经TCP/IP诞生到现代互联网的历史,我注意到一个转折点。我在之前的文章中也提到过:

    • 让网关作为一个信使而不是一个代理是一个好主意,这使网关的工作变得简单,只需转发数据包而无需拆解它。

    仔细一想,这个说法是依赖拓扑的。早期对网络的假设和现在完全不同。早期的假设是,所有节点组成一个P2P对等网络。所有节点是平等的。然而现代互联网却并非如此。

    我们来看CDN,CDN网络的cache节点,它既不是源节点,也不是目标节点,逻辑上,它位于网络核心,“让网关作为一个信使而不是一个代理是一个好主意”便错了,cache节点显然要理解数据,它不仅仅要做信使,还要做代理把信拆开。

    这属于对端到端原则的补充还是破坏?

    早期的P2P假设将网络视为一个对等通信的场所,类似于朋友之间的交流,直到现在我们的社交应用依然符合这种假设,除此之外,人们还将网络视为获取资源的场所,类似于卖场购物,图书馆借书,CDN网络便应运而生。在CDN网络中,中间节点变复杂了,这属实是一种对端到端原则的补充。

    然而如何将源站的端到端特征透明传输到客户终端,给中间cache节点带来很大的挑战。cache节点因此变得复杂无比,它需要理解各类源站的端到端特征,似乎它正朝向端到端原则的反面。

    除了CDN,数据中心网络亦是端到端原则的反动。各类源抑制,反压机制在交换机上完成精细化的加速,拥塞控制,端主机反而变得简单,省下本应该处理端到端逻辑的资源用于计算业务。数据中心网络核心越发复杂,而端主机越发简单,就像一根玉米棒子两端沾着两粒玉米粒。

    想多了,哪有什么普适原则。

    端到端原则的最佳实践就是可扩展性,适应变化,它制造了互联网的繁荣。CDN也好,数据中心也好,均是领域网络,它们并没有全球繁荣的所需,CDN仅调度资源到用户家门口,数据中心仅局限在百米范围,与全球互联网完全不同。

    因此,适应的才是最好的。

    最后,我做一个对比,铁路和公路。本来我想用TCP/IP网络和传统电信网络直接说的,可最终觉得还是铁路和公路最合适。

    铁路属于中心控制,复杂性在路网而不在火车,火车只保有启动,加速,刹车,鸣笛等简单功能即可。

    公路属于分布式控制,复杂性在汽车而不在公路,公路只保持平整的路面即可。

    试问,哪一种路更容易扩展,更适应变化?

    先看铁路,新加入一列火车,或者新接入一段铁路,必须对既有牵扯到的时间表调度做完全的调整,每次铁路新增列车,提速,都伴随着巨大的调整,所谓牵一发而动全身。

    再看公路,无论是经理新买了一辆新车上路,还是某处新修了一条路,什么都不用改变。汽车属于端到端逻辑,而公路只是一个极简的通道。

    铁路对变化的反应是强烈的,随着列车和路网的扩张,反应烈度是指数级增加的。

    公路对变化是无感的,各类新车在增加,各类旧车在淘汰,路有新修和拥堵,但几乎不会有任何感觉。

    浙江温州皮鞋湿,下雨进水不会胖。

    更多相关内容
  • 软件开发的201个原则v1.3.pdf
  • 原则英文版,总页数为586页,是完整的, 此版本是我付费在别的网站上下载的亲测好用,挺不错的资源,大家快来下载吧!挺有用的!需要的话可以来下载哦!
  • 系统总体设计原则

    2018-06-20 09:10:20
    信息化系统总体设计原则, 1.1 系统总体设计原则 1.2 业务应用支撑平台设计原则 1.3 共享交换区数据库设计原则
  • MySQL最左匹配原则,道儿上兄弟都得知道的原则

    千次阅读 多人点赞 2020-09-11 19:31:00
    目录一、最左匹配原则的原理二、违背最左原则导致索引失效的情况三、查询优化器偷偷干了哪些事儿四、需要你mark的知识点1、如何通过有序索引排序,避免冗余执行order by2、like 语句的索引问题3、不要在列上进行运算...

      自MySQL5.5版本起,主流的索引结构转为B+树。B+树的节点存储索引顺序是从左向右存储,在检索匹配的时候也要满足自左向右匹配。

      通常我们在建立联合索引的时候,相信建立过索引的同学们会发现,无论是Oracle还是 MySQL 都会让我们选择索引的顺序,比如我们想在a,b,c三个字段上建立一个联合索引,我们可以选择自己想要的优先级,(a、b、c),或是 (b、a、c) 或者是(c、a、b) 等顺序。
    在这里插入图片描述

      为什么数据库会让我们选择字段的顺序呢?不都是三个字段的联合索引么?这里就引出了数据库索引的最重要的原则之一,最左匹配原则

      在我们开发中经常会遇到这种问题,明明这个字段建了联合索引,但是SQL查询该字段时却不会使用这个索引。难道这索引是假的?白嫖老子资源?!

    比如索引abc_index:(a,b,c)是a,b,c三个字段的联合索引,下列sql执行时都无法命中索引abc_index;

    select * from table where c = '1';
    
    select * from table where b ='1' and c ='2';
    

    以下三种情况却会走索引:

    select * from table where a = '1';
    
    select * from table where a = '1' and b = '2';
    
    select * from table where a = '1' and b = '2'  and c='3';
    

      从上面两个例子大家有木有看出点眉目呢?

      是的,索引abc_index:(a,b,c),只会在where条件中带有(a)、(a,b)、(a,b,c)的三种类型的查询中使用。其实这里说的有一点歧义,其实当where条件只有(a,c)时也会走,但是只走a字段索引,不会走c字段。

      那么这都是为什么呢?我们一起来看看其原理吧。

    一、最左匹配原则的原理

    MySQL 建立多列索引(联合索引)有最左匹配的原则,即最左优先:
    如果有一个 2 列的索引 (a, b),则已经对 (a)、(a, b) 上建立了索引;
    如果有一个 3 列索引 (a, b, c),则已经对 (a)、(a, b)、(a, b, c) 上建立了索引;

    假设数据 表 LOL (id,sex,price,name) 的物理位置(表中的无序数据)如下:
    (注:下面数据是测试少量数据选用的,只为了方便大家看清楚。实际操作中,应按照使用频率、数据区分度来综合设定索引顺序喔~)

    主键id  sex(a)   price(b)      name(c)    
    (1)     1         1350         AAA安妮
    (2)     2         6300         MMM盲僧
    (3)     1         3150         NNN奈德丽
    (4)     2         6300         CCC锤石
    (5)     1         6300         LLL龙女
    (6)     2         3150         EEE伊泽瑞尔
    (7)     2         6300         III艾克
    (8)     1         6300         BBB暴走萝莉
    (9)     1         4800         FFF发条魔灵
    (10)    2         3150         KKK卡牌大师
    (11)    1         450          HHH寒冰射手
    (12)    2         450          GGG盖伦
    (13)    2         3150         OOO小提莫
    (14)    2         3150         DDD刀锋之影
    (15)    2         6300         JJJ疾风剑豪
    (16)    2         450          JJJ剑圣
    

      当你在LOL表创建一个联合索引 abc_index:(sex,price,name)时,生成的索引文件逻辑上等同于下表内容(分级排序)

    sex(a)   price(b)       name(c)         主键id
    1        450            HHH寒冰射手      (11)
    1        1350           AAA安妮          (1)
    1        3150           NNN奈德丽        (3)
    1        4800           FFF发条魔灵       (9)
    1        6300           BBB暴走萝莉       (8)
    1        6300           LLL龙女          (5)
    2        450            GGG盖伦          (12)
    2        450            JJJ剑圣          (16)
    2        3150           DDD刀锋之影       (14)
    2        3150           EEE伊泽瑞尔       (6)
    2        3150           KKK卡牌大师       (10)
    2        3150           OOO小提莫         (13)
    2        6300           CCC锤石          (4)
    2        6300           III艾克          (7)
    2        6300           JJJ疾风剑豪       (15)
    2        6300           MMM盲僧          (2)
    

      小伙伴儿们有没有发现B+树联合索引的规律?感觉还有点模糊的话,那咱们再来看一张索引存储数据的结构图,或许更明了一些。

    在这里插入图片描述
      这是一张来自思否上的图片,层次感很清晰,小伙伴可以看到,对于B+树中的联合索引,每级索引都是排好序的。联合索引 bcd_index:(b,c,d) , 在索引树中的样子如图 , 在比较的过程中 ,先判断 b 再判断 c 然后是 d 。

      由上图可以看出,B+ 树的数据项是复合的数据结构,同样,对于我们这张表的联合索引 (sex,price,name)来说 ,B+ 树也是按照从左到右的顺序来建立搜索树的,当SQL如下时:

    select sex,price,name from LOL where sex = 2 and price = 6300 and name = 'JJJ疾风剑豪'; 
    

      B+ 树会优先比较 sex 来确定下一步的指针所搜方向,如果 sex 相同再依次比较 price 和 name,最后得到检索的数据;

    二、违背最左原则导致索引失效的情况

    (下面以联合索引 abc_index:(a,b,c) 来进行讲解,便于理解)
    1、查询条件中,缺失优先级最高的索引 “a”
      当 where b = 6300 and c = 'JJJ疾风剑豪' 这种没有以 a 为条件来检索时;B+树就不知道第一步该查哪个节点,从而需要去全表扫描了(即不走索引)。因为建立搜索树的时候 a 就是第一个比较因子,必须要先根据 a 来搜索,进而才能往后继续查询b 和 c,这点我们通过上面的存储结构图可以看明白。

    2、查询条件中,缺失优先级居中的索引 “b”
      当 where a =1 and c =“JJJ疾风剑豪” 这样的数据来检索时;B+ 树可以用 a 来指定第一步搜索方向,但由于下一个字段 b 的缺失,所以只能把 a = 1 的数据主键ID都找到,通过查到的主键ID回表查询相关行,再去匹配 c = ‘JJJ疾风剑豪’ 的数据了,当然,这至少把 a = 1 的数据筛选出来了,总比直接全表扫描好多了。

      这就是MySQL非常重要的原则,即索引的最左匹配原则。

    三、查询优化器偷偷干了哪些事儿

    当对索引中所有列通过"=" 或 “IN” 进行精确匹配时,索引都可以被用到。

    1、如果建的索引顺序是 (a, b)。而查询的语句是 where b = 1 AND a = ‘陈哈哈’; 为什么还能利用到索引?

      理论上索引对顺序是敏感的,但是由于 MySQL 的查询优化器会自动调整 where 子句的条件顺序以使用适合的索引,所以 MySQL 不存在 where 子句的顺序问题而造成索引失效。当然了,SQL书写的好习惯要保持,这也能让其他同事更好地理解你的SQL。

    2、还有一个特殊情况说明下,下面这种类型的SQL, a 与 b 会走索引,c不会走。

    select * from LOL where a = 2 and b > 1000  and c='JJJ疾风剑豪';
    

      对于上面这种类型的sql语句;mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配(包括like '陈%'这种)。在a、b走完索引后,c已经是无序了,所以c就没法走索引,优化器会认为还不如全表扫描c字段来的快。所以只使用了(a,b)两个索引,影响了执行效率。

      其实,这种场景可以通过修改索引顺序为 abc_index:(a,c,b),就可以使三个索引字段都用到索引,建议小伙伴们不要有问题就想着新增索引哦,浪费资源还增加服务器压力。

      综上,如果通过调整顺序,就可以解决问题或少维护一个索引,那么这个顺序往往就是我们DBA人员需要优先考虑采用的。

    四、需要你mark的知识点

    1、如何通过有序索引排序,避免冗余执行order by

    order by用在select语句中,具备排序功能。如:

    SELECT sex, price, name FROM LOL ORDER BY sex;
    

    是将表 LOL 中的数据按 “sex” 一列排序。

      而只有当order by 与where 语句同时出现,order by的排序功能无效。换句话说,order by 中的字段在执行计划中利用了索引时,不用排序操作。如下SQL时,不会按 sex 一列排序,因为 sex 本身已经是有序的了。

    SELECT sex, price, name FROM LOL where sex = 1 ORDER BY sex ;
    

      所以,只有order by 字段出现在where条件中时,才会利用该字段的索引而避免排序。

    对于上面的语句,数据库的处理顺序是:

    • 第一步:根据where条件和统计信息生成执行计划,得到数据。

    • 第二步:将得到的数据排序。当执行处理数据(order by)时,数据库会先查看第一步的执行计划,看order by 的字段是否在执行计划中利用了索引。如果是,则可以利用索引顺序而直接取得已经排好序的数据。如果不是,则排序操作。

    • 第三步:返回排序后的数据。

    2、like 语句的索引问题

      如果通配符 % 不出现在开头,则可以用到索引,但根据具体情况不同可能只会用其中一个前缀,在 like “value%” 可以使用索引,但是 like “%value%” 违背了最左匹配原则,不会使用索引,走的是全表扫描。

    3、不要在列上进行运算

      如果查询条件中含有函数或表达式,将导致索引失效而进行全表扫描
    例如 :

    select * from user where YEAR(birthday) < 1990
    

    可以改造成:

     select * from users where birthday <1990-01-01

    4、索引不会包含有 NULL 值的列

      只要列中包含有 NULL 值都将不会被包含在索引中,复合索引中只要有一列含有 NULL 值,那么这一列对于此复合索引就是无效的。所以在数据库设计时不要让字段的默认值为 NULL

    5、尽量选择区分度高的列作为索引

      区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是 1,而一些状态、性别字段可能在大数据面前区分度就是 0。一般需要 join 的字段都要求区分度 0.1 以上,即平均 1 条扫描 10 条记录

    6、覆盖索引的好处

      如果一个索引包含所有需要的查询的字段的值,我们称之为覆盖索引。覆盖索引是非常有用的工具,能够极大的提高性能。因为,只需要读取索引,而无需读表,极大减少数据访问量,这也是不建议使用Select * 的原因。

    展开全文
  • 1. 加法原则 ( 1 ) 加法原则 ( 不能叠加 的事件才能用 加法原则 | 适用于 分类选取 ) ( 2 ) 乘法法则 ( 相互独立 的 事件 才能用 乘法法则 | 适用于 分步选择 ) 2. 习题解析 ( 1 ) 习题 1 ( 加法原理 ) ( 2 ) 习题 2...



    1. 加法原则



    ( 1 ) 加法原则 ( 不能叠加 的事件才能用 加法原则 | 适用于 分类选取 )


    加法原则 :

    • 1.加法法则描述 : 事件 A A A m m m 种 产生方式 , 事件 B B B n n n 种 产生方式 , 则 " 事件 A A A B B B " 有 m + n m + n m+n 种产生方式 ;
    • 1.加法法则推广 :事件 A 1 , A 2 , . . . , A n A_{1} , A_{2} , ... , A_{n} A1,A2,...,An 分别有 p 1 , p 2 , . . . , p n p_{1} , p_{2} , ... , p_{n} p1,p2,...,pn 种 产生方式 , 若 其中 任何 两个 事件 产生的方式 都 不重叠 , 则 " 事件 A 1 A_{1} A1 A 2 A_{2} A2 或 … 或 A n A_{n} An " 产生的方式 是 p 1 + p 2 + . . . + p n p_{1} + p_{2} + ... + p_{n} p1+p2+...+pn ;
    • 2.注意点 : 这里的 事件 A 1 , A 2 , . . . , A n A_{1} , A_{2} , ... , A_{n} A1,A2,...,An 必须是 不能重叠的 , 即 只有 一件 事件 发生 , 如果有多个 事件 同时发生 , 就必须 使用 乘法原则 ;
    • 3.适用问题 : 分类选取 ;



    ( 2 ) 乘法法则 ( 相互独立 的 事件 才能用 乘法法则 | 适用于 分步选择 )


    乘法原则 :

    • 1.乘法法则描述 : 事件 A 有 m 种 产生方式 , 事件 B 有 n 种 产生方式 , 则 " 事件 A 与 B " 有 mn 种产生方式 ;
    • 1.乘法法则推广 :事件 A 1 , A 2 , . . . , A n A_{1} , A_{2} , ... , A_{n} A1,A2,...,An 分别有 p 1 , p 2 , . . . , p n p_{1} , p_{2} , ... , p_{n} p1,p2,...,pn 种 产生方式 , 若 其中 任何 两个 事件 产生的方式 都 相互独立 , 则 " 事件 A 1 A_{1} A1 A 2 A_{2} A2 或 … 或 A n A_{n} An " 产生的方式 是 p 1 p 2 . . . p n p_{1} p_{2} ... p_{n} p1p2...pn ;
    • 2.注意点 : 这里的 事件 A 1 , A 2 , . . . , A n A_{1} , A_{2} , ... , A_{n} A1,A2,...,An 必须是 相互独立 的 ;
    • 3.适用问题 : 分步选取 ;



    2. 习题解析



    ( 1 ) 习题 1 ( 加法原理 )


    题目 :

    汽车市场 有 卡车 15 辆 , 面包车 8 辆 , 轿车 20 辆 ;
    从市场中只购买一辆车 , 有多少种购买方式 ?


    解答 :

    ① 这里用到了 加法原则 , 如果只能 买 一辆车的话 , 三种车 只能买一种 , 三个事件 是不能重叠的 ;

    ② 买卡车 有 15 种方式 , 买面包车 有 8 种方式 , 买轿车 有 20 种 , 三种方式只能选择一种 , 三者不能重叠 ( 同时存在 ) , 因此使用加法原则 进行计算 ;

    ③ 结果是 : 15 + 8 + 20 = 43 ;




    ( 2 ) 习题 2 ( 加法原则 乘法原则 综合运用 )


    A , B , C A , B , C A,B,C 是 3 个城市 ,
    A A A B B B 有 3 条路 , B B B C C C 有 2 条路 , A A A C C C 4 4 4 条路 ,
    问 从 A A A C C C 有多少种不同的方式 ?


    解 :

    加法原则 :
    ① 直接从 A A A C C C 与 ② 从 A A A 先到 B B B 再到 C C C 是 不能重叠的 , 方案 ① 与 方案 ② 需要 用家法原则 ,

    乘法原则 :
    方案 ② 内部需要使用 乘法原则 即 A A A B B B 有 3 种 选择 , B B B C C C 有 2 种选择 , 这两个选择是相互独立的 , 需要分步 选择 , 3 ∗ 2 = 6 3 * 2 = 6 32=6 ;

    最终 N = 3 × 2 + 4 = 10 N = 3 \times 2 + 4 = 10 N=3×2+4=10 ;




    ( 3 ) 习题 3 ( 乘法原则 )


    题目 :

    1000 1000 1000 9999 9999 9999 的 整数 中 :

    ① 含有5的数有多少个 ;
    ② 含有多少个 百位 和 十位数 均为 奇数 的 偶数 ;
    ③ 各位数 都不相同 的 奇数 有多少个;


    解答 :

    ( 1 ) 含有 5 的数 的个数 :

    ① 设 数字 集合 { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } \{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 \} {0,1,2,3,4,5,6,7,8,9}

    ② 直接求 含有 5 5 5 的数 , 比较麻烦 : 这里可以分成 1 1 1 位 含有 5 5 5 的数 , 此时又分成 个位 十位 百位 千位 四种情况 , 2 2 2 位 或 3 3 3 位 含有 5 5 5 更加复杂 ;

    ③ 这里 可以 转换一下思路 , 求 不含 5 的个数 :

    • 1> 千位 : 千位数 不能 取 0 0 0 5 5 5 , 只能取值 8 8 8 种情况 ;
    • 2> 百位 : 百位数 不能 取 5 5 5 , 9 9 9 种 取值情况 ;
    • 3> 十位 : 百位数 不能 取 5 5 5 , 9 9 9 种 取值情况 ;
    • 4> 个位 : 百位数 不能 取 5 5 5 , 9 9 9 种 取值情况 ;

    根据乘法原则 : 不含 5 5 5 的个数位为 8 × 9 × 9 × 9 = 5832 8 \times 9\times 9\times 9 = 5832 8×9×9×9=5832
    含有 5 的个数为 : 9000 − 5832 = 3168 9000 - 5832 = 3168 90005832=3168 ;



    ( 2 ) 百位 和 十位数 均为 奇数 的 偶数 :

    分析 四位 数 取值方案数 :

    • 1> 个位数取值方案数 : 考虑偶数的情况 : 如果为 偶数 , 那么 个位数 只能取值 { 0 , 2 , 4 , 6 , 8 } \{0, 2, 4 , 6, 8\} {0,2,4,6,8} 5 5 5 种情况 ;
    • 2> 十位数 和 百位数 取值 方案数 : 十位数 百位数 都是 奇数 , 那么 其 取值 { 1 , 3 , 5 , 7 , 9 } \{1 , 3 , 5 , 7 , 9 \} {1,3,5,7,9} , 也是 5 5 5 种方案 ;
    • 3> 千位数 取值 方案数 : { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } \{1 , 2, 3, 4, 5, 6, 7, 8, 9\} {1,2,3,4,5,6,7,8,9} , 有 9 9 9 种方案 ;

    根据 乘法 原则 : 百位 和 十位 均为 奇数 的 偶数 有 9 × 5 × 5 × 5 = 1125 9 \times 5 \times 5 \times 5 = 1125 9×5×5×5=1125 个 ;



    ( 3 ) 各位数 都不相同 的 奇数 个数 :

    逐位分析 :

    • 1> 分析 个位数 取值 : 个位数 如果不做限制的话 , 有 10 10 10 种方案数 { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } \{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 \} {0,1,2,3,4,5,6,7,8,9} , 要求 是 奇数 , 因此 个位数 只有 5 5 5 中方案 , 只能从 { 1 , 3 , 5 , 7 , 9 } \{1,3,5,7,9\} {1,3,5,7,9} 中取值 ;
    • 2> 分析 千位 的取值 : 千位数 不做限制的话 有 9 9 9 种方案 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } \{1, 2, 3, 4, 5, 6, 7, 8,9\} {1,2,3,4,5,6,7,8,9} , 如果要求 与 个位数不同 , 那么有 8 8 8 种方案 ;
    • 3> 分析 百位 数取值 : 百位数 如果不做限制的话 , 有 10 10 10 种方案数 { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } \{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 \} {0,1,2,3,4,5,6,7,8,9} , 千位 与 个位 各自 取了 一位数 , 那么只能下 8 8 8 种 方案数 ;
    • 4> 分析 十位 数取值 : 十位数 如果不做限制的话 , 有 10 10 10 种方案数 { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } \{0, 1, 2, 3, 4, 5, 6, 7, 8, 9 \} {0,1,2,3,4,5,6,7,8,9} , 千位 , 个位 与 百位 各自 取了 一位数 , 那么只能下 7 7 7 种 方案数 ;

    根据乘法原则 : 1000 1000 1000 9999 9999 9999 的整数中 , 各个位数 都 不相同的 奇数 有 5 × 8 × 7 × 7 = 2240 5 \times 8 \times 7 \times 7 = 2240 5×8×7×7=2240 ;


    每一位分析的先后顺序很有讲究 , 一般先分析 条件限制比较苛刻的 选择 , 在分析 比较宽松的选择 ;


    关于一一对应 的说明 :
    如果 性质 A A A 的 计数 比较困难 , 性质 B B B 的计数比较容易 , 性质 A A A 和 性质 B B B 存在一一对应 , 那么对性质 A A A 的计数 , 可以转化为 对 性质 B B B 的计数 ;
    这里用到了 一一对应 , 如 上述 , 计数 含有 5 5 5 的整数个数 , 如果正面计数比较困难 , 可以反过来 计算 不含有 5 5 5 的整数个数 , 这样就比较好计数了 , 1000 1000 1000 9999 9999 9999 一共有 9000 9000 9000 个数 , 9000 − 不 含 5 的 整 数 个 数 9000 - 不含5的整数个数 90005 与 含有 5 5 5 的整数个数 是一一对应的 ;


    常用的一一对应 :
    ① 选取问题
    ② 不定方程非负整数解问题
    ③ 非降路径问题
    ④ 正整数拆分问题
    ⑤ 放球问题


    展开全文
  • android 24种设计模式介绍与6大设计原则
  • 敏捷软件开发:原则、模式与实践(带书签,源码)
  • 7 大程序设计原则

    千次阅读 多人点赞 2021-05-05 11:44:20
    编程的工作既是技术活,也是体力活,而编写优秀的软件,更是一件比较难的事情。 初级程序员只希望代码不出错,顶级程序员却把写代码当成艺术,当年雷军以过人的能力成为...那大牛们都遵循怎样的原则呢,我们能不能学...

    编程的工作既是技术活,也是体力活,而编写优秀的软件,更是一件比较难的事情。

    初级程序员只希望代码不出错,顶级程序员却把写代码当成艺术,当年雷军以过人的能力成为求伯君的左膀右臂,其早年的代码被说成“像诗一样优美”。

    很多大牛,在着手写代码时并不是直接上手编写,而是根据需求进行设计,不但将代码中 Bug 出现的机率降到最低,还让代码具有高可读性,高安全性等等。

    那大牛们都遵循怎样的原则呢,我们能不能学习一下?

    将大牛们的经验总结到一起,可以得到以下「7 大程序设计原则」 。这些设计原理源于对实际软件开发现场的分析,是提高代码质量的经验结晶。

    让我们一起一探究竟吧!

    01 简单性原则

    Simplicity Principle

    What:追求简单
    简单性原则就是追求简单。

    说得极端一点,就是自始至终都以最简单的逻辑编写代码,让编程初学者一眼就能看懂。

    因此,在编程时我们要重视的是局部的完整性,而不是复杂的整体关联性。

    Why:Bug 喜欢出现在复杂的地方
    软件故障常集中在某一个区域,而这些区域都有一个共同的特点,那就是复杂。编写代码时如果追求简单易懂,代码就很难出现问题。

    不过,简单易懂的代码往往给人一种不够专业的感觉。这也是经验老到的程序员喜欢写老练高深的代码的原因。所以我们要有足够的定力来抵挡这种诱惑。

    Do:编写自然的代码
    努力写出自然的代码。放下高超的技巧,坚持用简单的逻辑编写代码。

    既然故障集中在代码复杂的区域,那我们只要让代码简单到让故障无处可藏即可。不要盲目地让代码复杂化、臃肿化,要保证代码简洁。

    02 同构原则

    Isomorphism Principle

    What:力求规范
    同构原则就是力求规范。

    同等对待相同的东西,坚持不搞特殊。同等对待,举例来说就 是同一个模块管理的数值全部采用同一单位、公有函数的参数个数统一等。

    Why:不同的东西会更显眼
    相同的东西用相同的形式表现能够使不同的东西更加突出。不同的 东西往往容易产生 bug。遵循同构原则能让我们更容易嗅出代码的异样, 从而找出问题所在。

    图表和工业制品在设计上追求平衡之美,在这一点上,同构原则也 有着相似之处。统一的代码颇具美感,而美的东西一般更容易让人接 受,因此统一的代码有较高的可读性。

    Do:编写符合规范的代码
    我们要让代码符合一定的规范。不过,这会与程序员的自我表现欲相冲突。

    为了展现自己的实力,有些程序员会无视编程规范,编写独特的代码。可靠与简单是代码不可或缺的性质,但这些程序员常常在无意间让代码变得复杂。

    这就把智慧与个性用错了地方。小小的自我满足远不及代码质量重要。所以在编写代码时,务必克制住自己的表现欲,以规范为先。

    03 对称原则

    Symmetry Principle

    What:讲究形式上的对称
    讲究形式上的对称。

    对称原则就是讲究形式上的对称,比如有上就有下,有左就有右, 有主动就有被动。

    也就是说,我们在思考一个处理时,也要想到与之成对的处理。比 如有给标志位置 1 的处理,就要有给标志位置 0 的处理。

    Why:帮助读代码的人推测后面的代码
    具有对称性的代码能够帮助读代码的人推测后面的代码,提高其理解代码的速度。同时,对称性会给代码带来美感,这同样有助于他人理解代码。

    此外,设计代码时将对称性纳入考虑的范围能防止我们在思考问题时出现遗漏。如果说代码的条件分支是故障的温床,那么对称性就是思考的框架,能有效阻止条件遗漏。

    Do:编写有对称性的代码
    在出现“条件”的时候,我们要注意它的“反条件”。每个控制条件都存在与之成对的反条件(与指示条件相反的条件)。要注意条件与反条件的统一,保证控制条件具有统一性。

    我们还要考虑到例外情况并极力避免其发生。例外情况的特殊性会破坏对称性,成为故障的温床。特殊情况过多意味着需求没有得到整理。此时应重新审视需求,尽量从代码中剔除例外情况。

    命名也要讲究对称性。命名时建议使用 set/get、start/stop、begin/ end 和 push/pop 等成对的词语。

    04 层次原则

    Hierarchy Principle

    What:讲究层次
    注意事物的主从关系、前后关系和本末关系等层次关系,整理事物的关联性。

    不同层次各司其职,同种处理不跨越多个层次,这一点非常重要。比如执行了获取资源的处理,那么释放资源的处理就要在相同的层次进行。又比如互斥控制的标志位置 1 和置 0 的处理要在同一层次进行。

    Why:层次结构有助于提高代码的可读性
    有明确层次结构的代码能帮助读代码的人抽象理解代码的整体结构。读代码的人可以根据自身需要阅读下一层次的代码,掌握更加详细的信息。

    这样一来就可以提高代码的可读性,帮助程序员表达编码意图,降低 bug 发生的概率。

    Do:编写有抽象层次结构的代码
    在编写代码时设计各部分的抽象程度,构建层次结构。保证同一个层次中的所有代码抽象程度相同。另外,高层次的代码要通过外部视角描述低层次的代码。这样做能让调用低层次代码的高层次代码更加简单易懂。

    05 线性原则

    Linearity Principle

    What:处理流程尽量走直线
    线性原则就是让处理流程尽量走直线。

    一个功能如果可以通过多个功能的线性结合来实现,那它的结构就会非常简单。

    反过来,用条件分支控制代码、毫无章法地增加状态数等行为会让代码变得难以理解。我们要避免做出这些行为,提高代码的可读性。

    Why:直线处理可提高代码的可读性
    复杂的处理流程是故障的温床。

    故障多出现在复杂的条件语句和循环语句中。另外,goto 等让流程出现跳跃的语句也是故障的多发地。

    如果能让处理由高层次流向低层次,一气呵成,代码的可读性就会大幅提高。与此同时,可维护性也将提高,添加功能等改良工作将变得更加容易。

    一般来说,自上而下的处理流程简单明快,易于理解。我们应避开复杂反复的处理流程。

    Do:尽量不在代码中使用条件分支
    尽量减少条件分支的数量,编写能让代码阅读者线性地看完整个处理流程的代码。

    为此,我们需要把一些特殊的处理拿到主处理之外。保证处理的统一性,注意处理的流程。记得时不时俯瞰代码整体,检查代码是否存在过于复杂的部分。

    另外,对于经过长期维护而变得过于复杂的部分,我们可以考虑对其进行重构。明确且可靠的设计不仅对我们自身有益,还可以给负责维护的人带来方便。

    06 清晰原则

    Clarity Principle

    What:注意逻辑的清晰性
    清晰原则就是注意逻辑的清晰性。

    逻辑具有清晰性就代表逻辑能清楚证明自身的正确性。也就是说,我们编写的代码要让人一眼就能判断出没有问题。任何不明确的部分都 要附有说明。

    保证逻辑的清晰性要“不择手段”。在无法用代码证明逻辑正确性的情况下,我们也可以通过写注释、附文档或画图等方法来证明。不过,证明逻辑的正确性是一件麻烦的事,时间一长,人们就会懒得用辅助手段去证明,转而编写逻辑清晰的代码了。

    Why:消除不确定性
    代码免不了被人一遍又一遍地阅读,所以代码必须保持较高的可读性。编写代码时如果追求高可读性,我们就不会采用取巧的方式编写代码,编写出的代码会非常自然。

    采用取巧的方式编写的代码除了能让计算机运行以外没有任何意义。代码是给人看的,也是由人来修改的,所以我们必须以人为对象来编写代码。

    消除代码的不确定性是对自己的作品负责,这么做也可以为后续负责维护的人提供方便。

    Do:编写逻辑清晰的代码
    我们要编写逻辑清晰的代码。

    为此,我们应选用直观易懂的逻辑。会给读代码的人带来疑问的部分要么消除,要么加以注释。

    另外,我们应使用任何人都能立刻理解且不存在歧义的术语。要特别注意变量名等一定不能没有意义。

    07 安全原则

    Safty Principle

    What:注意安全性
    安全原则就是注意安全性,采用相对安全的方法来对具有不确定性的、模糊的部分进行设计和编程。

    说得具体一点,就是在编写代码时刻意将不可能的条件考虑进去。比如即便某个 i f 语句一定成立,我们也要考虑 else 语句的情况;即便某个 case 语句一定成立,我们也要考虑 default 语句的情况;即便某个变量不可能为空,我们也要检查该变量是否为 NULL。

    Why:防止故障发展成重大事故
    硬件提供的服务必须保证安全,软件也一样。

    硬件方面,比如取暖器,为防止倾倒起火,取暖器一般会配有倾倒自动断电装置。同样,设计软件时也需要考虑各种情况,保证软件在各种情况下都能安全地运行。这一做法在持续运营服务和防止数据损坏等方面有着积极的意义。

    Do:编写安全的代码
    选择相对安全的方法对具有不确定性的部分进行设计。列出所有可能的运行情况,确保软件在每种情况下都能安全运行。理解需求和功能,将各种情况正确分解到代码中,这样能有效提高软件安全运行的概率。

    为此,我们也要将不可能的条件视为考察对象,对其进行设计和编程。不过,为了统一标准,我们在编写代码前最好规定哪些条件需要写,哪些条件不需要写。

    摘自:《编程的原则:程序员改善代码质量的 101 个方法》
    作者:[日]上田勋

    展开全文
  • 以前本站向大家介绍过一些软件开发的原则,比如优质代码的十诫和Unix传奇(下篇)中所以说的UNIX的设计原则。相信大家从中能够从中学了解到一些设计原理方面的知识,正如我在《再谈“我是怎么招聘程序”》中所说的,一...
  • Java开发设计——七大原则

    千次阅读 多人点赞 2021-02-21 10:20:47
    一、开闭原则(Open Closed Principle,OCP) 含义 开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。 作用 开闭原则是面向对象程序...
  • 软件设计的七大原则——超详细

    千次阅读 2020-04-05 21:33:16
    设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同。其中: 开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭; 里氏替换原则告诉我们不要破坏继承体系; 依赖倒置原则告诉我们要面向接口...
  • PMP 考试原则

    千次阅读 2019-12-08 10:54:11
    原则1:会分类,能排序。 分类和排序是项目经理的基本功,涉及面广,用处大。 问题和变更日志、需求文件、可交付成果、活动清单、预算表、质量指标、干系人、风险、供应商等等都涉及到分类,亲和图可用于分类。 通过...
  • 软件开发的201个原则

    千次阅读 2021-11-09 09:46:09
    第2章 一般原则原则1 质量 原则2 质量在每个人眼中都不同 原则3 开发效率和质量密不可分 原则4 高质量软件是可以实现的 原则5 不要试图通过改进软件实现高质量 原则6 低可靠性比低效率更糟糕 原则7 尽早...
  • 系统建设原则

    千次阅读 2022-04-07 10:23:21
    高可用性原则 鉴于系统的高可用性目标是项目目标的关键组成部分,按照业界高可用性设计方法,系统的高可用性设计将着重从“3R”方面考虑: (1)ROBUST 系统的关键应用软件组件在开发时需要能够处理各种已预计到的...
  • 代码开发原则

    千次阅读 2022-01-19 16:08:10
    工作中常用原则记录,随时更新
  • 设计模式六大原则

    千次阅读 2021-04-10 16:57:25
    设计模式共23种,分为创建型、行为型、结构型三大类。 创建型:对类的现实化进行了抽象,...设计模式总原则:开闭原则,即对扩展开放,对修改关闭。 1.开放封闭原则(Open - ClosedPrinciple ,OCP) 定义:一...
  • 设计模式的六大原则

    万次阅读 多人点赞 2019-05-16 17:50:03
    一、单一职责原则(Single Responsibility Principle) 二.开闭原则(Open-Closed Principle, OCP) 三、里氏代换原则(Liskov Substitution Principle, LSP) 四、依赖倒置原则(Dependence Inversion Principle,...
  • Python——设计原则

    千次阅读 2021-07-13 14:46:21
    单一职责原则 对类来说的,即一个类应该只负责一项职责。如类A负责两个不同职责(职责1和职责2),当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为 A1和A2。总体来说,单一职责可以...
  • 尼尔森十大交互设计原则

    千次阅读 2019-04-21 12:16:30
    Jakob Nielsen(雅各布·尼尔森)的十大交互设计原则。它们被称为“启发式”,因为它们是广泛的经验法则,而不是特定的可用性指导原则。因此,我们不能把它上升为一种标准,而是应该当做一种经验来学习,然后跟现实...
  • 设计原则硬核干货

    千次阅读 热门讨论 2021-05-21 22:39:44
    一篇文章帮你拿下设计模式的核心:设计原则,万字长文 以下所有的原则,都不能脱离应用场景!! 很多人都有过编写代码时候无所适从,无法写出十分优雅,高效的代码。 也有些人在翻阅设计模式的时候摸不透各种奇奇怪...
  • 数据库设计原则

    千次阅读 2019-06-09 09:52:33
    一,数据库设计原则 1. 原始单据与实体之间的关系  可以是一对一、一对多、多对多的关系。在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体。 在特殊情况下,它们可能是一对多或多对一的...
  • 面向对象设计的七大原则(包括SOLID原则原则概述1. 单一职责原则(Single Responsibility Principle)2. 开闭原则(Open Close Principle)3. 里氏替换原则(Liskov Substitution Principle)4. 接口隔离原则...
  • 面向对象七大设计原则

    千次阅读 2020-06-15 23:49:37
    面向对象设计的七大原则 前言 在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,我们能要尽量根据 7 条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。 面向...
  • 安全(Security)设计原则(1)

    千次阅读 2022-01-18 17:21:13
    开发安全相关系统时,ISO/SAE 21434:2021建议遵循安全领域的设计原则。 ISO/SAE 21434:2021 Clause 10.4 [RC-10-06] Established and trusted design and implementation principles should be applied to avoid or ...
  • 3W原则 在PCB设计中为了减少线间串扰,应保证线间距足够大,当线中心间距不少于3倍线宽时,则可保持大部分电场不互相干扰,这就是3W规则。 满足3W原则能使信号间的串扰减少70%,而满足10W则能使信号间的串扰减少近98...
  • 微服务设计原则之AKF原则

    千次阅读 2020-12-17 15:42:43
    在设计微服务的时候,我们一般会遵循以下4个原则: 1)AKF拆分原则 2)前后端分离原则 3)无状态服务 4)restful的通信风格 AKF把系统扩展分为以下三个维度: X轴:直接水平复制应用进程来扩展系统,将系统...
  • 英语“就近原则”和“就远原则

    万次阅读 2019-09-03 06:37:18
    什么是“就近原则”?什么是“就远原则”?是根据单词位置的“近”或“远”来判断的吗?在回答之前先做一道例子。 例1.What he does or what he says __ nothing to do with me. 他的行为或言谈都与我无关。 在这个...
  • 六大原则之开闭原则

    千次阅读 2021-02-02 10:23:59
    1. 开闭原则的介绍 开闭原则(Open Closed Principle)是编程中最基础、最重要设计原则 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。 当...
  • 阅读《原则》有感之工作原则

    千次阅读 2018-12-03 17:15:03
    ***任何组织或机构,若想正常运转,其工作原则就必须与其成员的生活原则相契合。 一、打造良好的文化。。。 1、相信极度求真和极度透明  1.1、不要惧怕了解事实  1.2、为人要正直,也要要求他人保持...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,439,497
精华内容 575,798
关键字:

原则

友情链接: 2275_20100624.rar