精华内容
下载资源
问答
  • 以太网的实现采用层次结构的概念,每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持,每一层都为上一层功能的实现打好基础。 实际上,用户接触到的只是最上面的一层,根本感觉不到底层的存在。要理解与...

    以太网的实现采用层次结构的概念,每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持,每一层都为上一层功能的实现打好基础。

    实际上,用户接触到的只是最上面的一层,根本感觉不到底层的存在。要理解与以太网,必须从最下层开始,自下而上理解每一层的功能。

    五层结构

    以太网的模型有不同的分层方式,ISO(国际标椎组织)提出OSI七层网络模型,自上而下分别为:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。OSI七层模型主要是为了解决异种网络互连时所遇到的兼容性问题。它最大的优点是将服务,接口和协议这三个概念明确区分来,也使网络的不同功能模块承担起不同的职责。由于互联网网络体系结构以TCP/IP协议为核心 ,因而基于TCP/IP的参考模型将以太网可以分为四层,自上而下分别为:应用层,传输层,网络互联层,网络接口层。

    根据个人理解,把以太网分成五层比较容易理解。这五层结构不尽符合OSI结构强调的不同层次承担不同的职责的特点,同时也符合TCP/IP协议参考模型协议之间互相支持,相互调用的逻辑关系。

    如上图所示,最底下的一层叫做'物理层',也叫作‘PHY层’,最上层的一层叫做“应用层”,中间的三层(自下而上)分别是“链路层”也叫“MAC层” “网络层”和“传输层”。越下面的层,越靠近硬件;越上面的层越接近用户。

    层与协议

    每一层都有其各自的功能,为了实现这些功能,需要大家都遵循一个共同的规则

    那么这个共同的规则,就叫做协议。以太网的每一层都定义了很多协议。这些协议的总称就叫做“互联网协议”,他们是互联网的核心,下面介绍每一层的功能,及其中的主要协议。

    下面对以太网的五层结构模型进行详细解释,让大家对网络的通信过程,每层的具体定义和功能,数据收发机制以及要遵守的协议进行理解。不同层由于封装包机制不同,数据的叫法也不同,这样有利于大家更好的理解下面的内容。传输层叫做段,网络层叫数据报,链路层叫做帧。

    物理层也叫作“PHY层”,它负责将上层所要发送的信息编码成电流脉冲或其他信号用于网上传输。

    物理层由计算机和网络介质之间的实际界面组成,可定义成电气信号,信号线的状态和时钟要求,数据编码和数据传输用的连接器。如常用的RS-232规范,曼彻斯特编码就属于这一层,所有比物理层高的层都通过事先定义好的接口而与他通话。

    链路层

    数据链路层通过物理网络链路提供可靠的数据传输。不同的数据链路层定义了不同的网络和协议特征,其中包括物理编址,网络拓扑结构,错误校验,帧序列以及流控

    物理编址(相对应的是网络编址)定义了设备在数据链路层的编址方式;网络拓扑结构定义了设备的物理连接方式,如总线拓扑结构和环拓扑结构,错误校验向发生传输错误的上层协议告警;数据帧序列重新整理并传输除序列以外的帧;流控可能延缓数据的传输以便接收设备不会因为在某一时刻接收到超过其处理能力的信息流而崩溃。

    以太网协议

    早期的时候,每家公司都有自己的电信号分组方式,后来逐渐形成了以“以太网”为主的一整套协议。

    以太网规定,一组电信号构成一个数据包,叫做“帧”,每一帧分成三个部分:以太网首部  数据 以及以太网尾部。

    “以太网首部”包括数据帧的一些说明项,比如发送者 接收者  数据类型等等  “数据”部分则是数据的具体内容;“以太网尾部”则是CRC校验码。

    以太网首部的长度固定为14字节。数据的长度最短为46字节,最长为1500字节,以太网尾部的长度固定4字节,因此整个帧最短为64字节,最长1518字节,如果数据很长,就必须分割成多个帧进行发送。

    MAC地址

    上面提到了  以太网数据帧的首部  包含了发送者和接收者的信息,那么发送者和接收者是如何标识的

    以数据链路层实际上由两个独立的部分组成   介质存取控制和逻辑链路控制层。MAC 描述在共享, 介质环境中如何进行站的调度、发生和接收数据。MAC 确保信息跨链路的可靠传输,对数据传输进行同步,识别错误和控制数据的流向。一般地讲,MAC 只在共享介质环境中才是重要的,只有在共享介质环境中多个节点才能连接到同一 传输介质上。IEEE MAC 规则定义了地址,也就是 MAC 地址,以标识数据链路层中的多个设备,因此链路层也叫“MAC 层”。

    每块网卡出厂的时候,都有一个全世界独一无二的 MAC 地址,长度是 48 个二进制位,通常用 12 个十六进制数表示。

    前 6 个十六进制数是厂商编号,后 6 个是该厂商的网卡流水号。有了 MAC 地址,就可以定位网卡和数据包的路径了。

    广播

    定义地址只是第一步, 那么一块网卡怎么会知道另一块网卡的 MAC 地址? ARP 协议可以解决这个问题。这个留到后面介绍,这里只需要知道,以太网数据帧必须知道接收方的 MAC 地址,然后才能发送。 其次,就算有了 MAC 地址,系统怎样才能把数据帧准确送到接收方?

    其实,以太网采用了一种很“原始”的方式,它不是把数据帧准确送到接收 方,而是向本网络内所有计算机发送,让每台计算机自己判断,是否为接收方。 它们读取这个帧的“首部”,找到接收方的 MAC 地址,然后与自身的 MAC 地址相比较,如果两者相同,就接受这个帧,做进一步处理,否则就丢弃这一帧。这种发送方式就叫做“广播”(broadcasting)。 有了数据帧的定义、网卡的 MAC 地址、广播的发送方式,“链路层”就可以 在多台计算机之间传送数据了。

    网络层

    网络层负责在源和终点之间建立连接。它一般包括网络寻径,还可能包括流量控制、错误检查等。相同 MAC 标准的不同网段之间的数据传输一般只涉及到数据链路层,而不同的 MAC 标准之间的数据传输都涉及到网络层。例如 IP 路由器工作在网络层,因而可以实现多种网络间的互联。

    规定网络地址的协议,叫做 IP 协议。它所定义的地址,就被称为 IP 地址。 目前,广泛采用的是 IP 协议第四版,简称 IPv4。这个版本规定,网络地址由 32 个二进制位组成。

    习惯上,我们用分成四段的十进制数表示 IP 地址,从 0.0.0.0 一直到 255.255.255.255。 互联网上的每一台计算机,都会分配到一个 IP 地址。这个地址分成两个部 分,前一部分代表网络,后一部分代表主机。比如,IP 地址 172.16.254.1,这 是一个 32 位的地址,假定它的网络部分是前 24 位(172.16.254),那么主机部分就是后 8 位(最后的那个 1)。处于同一个子网络的电脑,它们 IP 地址的网络部分必定是相同的,也就是说 172.16.254.2 应该与 172.16.254.1 处在同一个子网络。

    根据 IP 协议发送的数据,就叫做 IP 数据报。不难想象,其中必定包括 IP 地址信息。 但是前面说过,以太网数据帧只包含 MAC 地址,并没有 IP 地址的信息。那么是否需要修改数据定义,再添加 IP 地址信息呢? 答案是不需要,我们可以把 IP 数据报直接放进以太网数据帧的“数据”部分, 因此完全不用修改以太网的规格。这就是互联网分层结构的好处:上层的变动完全不涉及下层的结构。 具体来说,IP 数据报分为“标头”和“数据”两个部分。

    “标头”部分主要包括版本、长度、IP 地址等信息,“数据”部分则是 IP 数据报的具体内容。 IP 数据报的“标头”部分长度为 20 到 60 字节,整个数据报的总长度最大为 65,535 字节。因此理论上,一个 IP 数据报的“数据”部分,最长为 65,515 字 节。前面说过,以太网数据帧的“数据”部分,最长只有 1500 字节。因此,如 果 IP 数据报超过了 1500 字节,它就需要分割成几个以太网数据帧,分开发送了。

    传输层

    传输层向高层提供可靠的端到端的网络数据流服务。传输层的功能一般包括流控、多路传输、虚电路管理及差错校验和恢复。流控管理设备之间的数据传输, 确保传输设备不发送比接收设备处理能力大的数据;多路传输使得多个应用程序的数据可以传输到一个物理链路上;虚电路由传输层建立、维护和终止;差错校验包括为检测传输错误而建立的各种不同结构;而差错恢复包括所采取的行动 (如请求数据重发),以便解决发生的任何错误

    udp协议

    我们必须在数据包中加入端口信息,这就需要新的协议。最简单的实现叫做 UDP 协议,UDP 数据段也是由“标头”和“数据”两部分组成。

    “标头”部分主要定义了发出端口和接收端口,“数据”部分就是具体的内 容。然后,把整个 UDP 数据段放入 IP 数据报的“数据”部分,而 IP 数据报又是放在以太网数据帧之中的。 UDP 数据段非常简单,“标头”部分一共只有 8 个字节,总长度不超过 65,535 字节,正好放进一个 IP 数据报。

    TCP协议

    为了提高网络可靠性,诞生了 TCP 协议。这个协议非常复杂,但可以近似认为,它就是有确认机制的 UDP 协议,每发出一个数据都要求确认。如果有一个数据遗失,就收不到确认,发出方就知道有必要重发这个数据了。 TCP 协议能够确保数据不会遗失,缺点是过程复杂、实现困难、消耗较多的资源。TCP 数据段和 UDP 数据段一样,都是内嵌在 IP 数据报的“数据”部分。 TCP 数据段没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常 TCP 数据段的长度不会超过 IP 数据报的长度,以确保单个 TCP 数据段不必再分割。

    应用层

    应用层是最接近终端用户的第一层,这就意味着应用层和用户之间是通过应用软件直接相互作用的。注意,应用层并非由计算机上运行的实际应用软件组成,而是由向应用程序提供访问网络资源的API(应用程序接口)组成,应用层的功能一般包括标识通信伙伴,应用层必须为传输层数据的应用子程序定义通信伙伴的标识和可用性。定义资源可用性时,应用层为了请求通信而必须判定是否有足够的网络资源,在同步通信中,所有应用程序之间的通信都需要应用层的协同操作。

    应用程序收到“传输层”的数据,接下来就要进行解读。由于互联网是开放 架构,数据来源五花八门,必须事先规定好格式,否则根本无法解读。“应用层” 的作用,就是规定应用程序的数据格式。 应用层的 HTTP(超文本传输)协议、DNS(域名解析)协议、FTP(文件传送)协议、SMTP(简单邮件管理)协议等。

    举例来说,TCP 协议可以为各种各样的程序传递数据,比如发 Email 用的 SMTP(简单邮件管理)协议、网上冲浪用到的 HTTP(超文本传输)协议、下载资料用到的 FTP(文件传送)协议等等,这些应用程序协议就构成了“应用层”。 这是最高的一层,直接面对用户。它的数据就放在 TCP 数据段的“数据”部 分。因此,现在的以太网的数据帧就变成下图这样。

    至此,整个以太网的五层结构就介绍完毕。包括计算机和单片机在内的任何设备需要联网,就必须搭建这五层物理连接以及处理层内和层与层之间的 TCP/IP 协议方能实现网络应用。

    以太网的接入方案

    以太网的五层结构模型及各层所要实现的功能,按 照这一模型诞生出了各式各样的单片机网络连接方案来满足客户的不同要求。单片机的种类繁多,从低端到高端,有以 51 单片机为代表的 8 位单片机和以 ARM 为代表的 32 位单片机,不同档次的单片机实现网络接口的方法不同。对于像 ARM 等高端处理器一般都可以运行嵌入式操作系统,例如嵌入式 Linux。对于无操作系 统要求的单片机如何实现网络接入,我下面将这些方案按 TCP/IP 协议栈的不同归 结为两大类:第一类是传统的软件TCP/IP协议栈方案;第二类是最新的硬件TCP/IP 协议栈方案。下面我就这两类方案的实现方式进行分析。

    MAC + PHY方案

    所谓的 TCP/IP 协议栈是一系列网络协议的统称,不仅包括我们熟知的 TCP 协 议和 IP 协议,还有网络层的 ICMP(Internet 控制报文)协议、IGMP(Internet 组 管理)协议、ARP(地址解析)协议,传输层的 UDP(用户数据包)协议,应用层 的 HTTP(超文本传输)协议、DNS(域名解析)协议、FTP(文件传送)协议、 SMTP(简单邮件管理)协议等等。

    传统的以太网接入方案如下图,由 MCU+MAC+PHY 再加入网络接口实现以太网的物理连接,通过在主控芯片中植入 TCP/IP 协议代码实现通信及上层应用。

    应用这种软件TCP/IP。由于软件协议栈操作需要主控 MCU 不断地响应中断,这在很大程度上占用了 MCU 的运算/时钟资源。经过测试发现,单线程操作的情况下,MCU 的运行速度和数据的处理速度仅能满足需要,但随着线程增多,MCU 的工作效率直线下降,会 严重影响通信质量。

    代码量方面,即便是采用轻量级的 TCP/IP 协议栈 LWIP 协议,也会为主控芯 片带来超过 40KB 的代码量,这对于本身内存资源匮乏的单片机来说负荷过重。

    再从安全性的角度,设备并入互联网之后必须考虑网络安全问题,这种软件协 议栈的方式系统一旦受到复杂的恶意攻击,单片机很有可能瘫痪掉,这对系统就 是致命性打击,虽然目前网络技术不断发展,各类新的加密技术试图让通信变得 更加安全,但是还会出现各种各样的漏洞。

    硬件协议栈芯片方案

    硬件协议栈芯片方案如下图所示。由 MCU+硬件协议栈芯片(内含 MAC和 PHY) 直接加网络接口,便可方便的实现单片机联网,所有的处理 TCP/IP 协议的工作都 是通过这位 MCU 的“小秘书”——硬件协议栈芯片来完成。

    所谓硬件协议栈是指通过将传统的软件 TCP/IP 协议栈用硬件化的逻辑门电路 来实现,如下图所示。

    以太网芯片的内核由传输层的 TCP、UDP、ICMP、IGMP 等协议、网络层的 IP、 ARP、PPPoE 等协议以及链路层的 MAC 构成,再加上物理层的 PHY 和外围的寄存 器、内存、SPI 接口组成了这一整套硬件化的以太网解决方案。

    这套硬件 TCP/IP 协议栈代替了以往的 MCU 来处理这些中断请求,即 MCU 只 需要处理面向用户的应用层数据即可,传输层、网络层、链路层及物理层全部由 外围 WIZnet 的芯片完成。这套方案从硬件开销和软件开发两个方面来简化前面所 述的五层网络模型,简化产品开发方案。这样一来,工程师们就不必再面对繁琐 的通信协议代码,只需要了解简单的寄存器功能以及 Socket 编程便能完成产品开 发工作的的网络功能开发部分。

    由于硬件协议栈的加入协助单片机处理了几乎所有的 TCP/IP 协议工作,不仅 极大地减少了单片机的中断次数,让单片机腾出更多资源去完成其他工作,而且 硬件化的电路处理协议会更加快速、稳定。经试验测试,单线程下,该方案的通 信速度是软件协议方案的 10 倍左右;随着线程的增加,因为硬件协议栈是通过独 立的 Socket 进行通信,因而通信速度实现累加,而且单片机工作效率仍然会维持 在高位。

    代码量方面,因为这套方案主要是完成对 Socket 的编程以及寄存器的调用, 因此仅有 10K 左右的代码量,远小于软件协议方案,对 51 以及 STM32 等内存很 有限的单片机来说非常适用。

    从成本角度来讲,硬件协议栈芯片的价格跟用 MAC+PHY 比起来基本差不多。 而前者简单易用,用很短时间便能完成产品的开发过程。另外,官方例程库及上 位机程序丰富,也缩短了测试过程,后期基本免于维护。

    最后安全性方面,硬件化的逻辑门电路来处理 TCP/IP 协议是不可攻击的,也 就是说网络攻击和病毒对它无效,这也充分弥补了网络协议安全性不足的短板。 也正是因为这一优势,硬件协议栈技术在未来物联网以及智能家居领域有着广泛 的发展前景,让人们尽情享受现代科技带来的乐趣的同时,免受安全问题的困扰。

    当然,不可避免的硬件化的协议栈相对来说失去了软件协议栈那样的灵活性。 目前只支持 4 个/8 个 Socket,不能随时开启更多 Socket。但是,在嵌入式应用中 8 个 Socket 已经足够应对超过大部分的应用。

    展开全文
  • 程序员技能层次模型

    千次阅读 2015-03-15 19:22:01
    编程技能层次 编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本0段—非程序员: 初学编程者,遇到问题,完全是懵懵懂懂,不知道该怎么编程解决问题。也就是说,还是门外汉,还不能称之为“程序员...

    编程技能层次
    编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本

    0段—非程序员:
    初学编程者,遇到问题,完全是懵懵懂懂,不知道该怎么编程解决问题。也就是说,还是门外汉,还不能称之为“程序员”。计算机在他面前还是一个神秘的黑匣子。

    1段—基础程序员:
    学习过一段时间编程后,接到任务,可以编写程序完成任务。
    编写出来的代码,正常情况下是能够工作的,但在实际运行中,碰到一些特殊条件就会出现各类BUG。也就是说,具备了开发Demo软件的能力,但开发的软件真正交付给客户使用,恐怕会被客户骂死。
    程序员程序是写好了,但到底为什么它有时能正常工作,有时又不行,程序员自己也不知道。
    运行中遇到了bug,或者需求改变,需要修改代码或者添加代码,很快程序就变得结构混乱,代码膨胀,bug丛生。很快,就连最初的开发者自己也不愿意接手维护这个程序了。

    2段—数据结构
    经过一段时间的编程实践后,程序员会认识到“数据结构+算法=程序”这一古训的含义。他们会使用算法来解决问题。进而,他们会认识到,算法本质上是依附于数据结构的,好的数据结构一旦设计出来,那么好的算法也会应运而生。
    设计错误的数据结构,不可能生长出好的算法。
    记得某一位外国先贤曾经说过:“给我看你的数据结构!”

    3段—面向对象:
    再之后,程序员就会领略面向对象程序设计的强大威力。大多数现代编程语言都是支持面向对象的。但并不是说,你使用面向对象编程语言编程,你用上了类,甚至继承了类,你就是在写面向对象的代码了。
    我曾经见过很多用Java,Python,Ruby写的面向过程的代码。
    只有你掌握了接口,掌握了多态,掌握了类和类,对象和对象之间的关系,你才真正掌握了面向对象编程技术。
    就算你用的是传统的不支持面向对象的编程语言,只要你心中有“对象”,你依然可以开发出面向对象的程序。
    如,我用C语言编程的时候,会有意识的使用面向对象的技巧来编写和设计程序。用struct来模拟类,把同一类概念的函数放在一起模拟类。如果你怀疑用C语言是否能编写出面向对象的代码,你可以看一下Linux内核,它是用C语言编写的,但你也可以看到它的源代码字里行间散发出的浓浓的“对象”的味道。
    真正掌握面向对象编程技术并不容易。
    在我的技术生涯中,有两个坎让我最感头疼。
    一个坎是Dos向Windows开发的变迁过程中,框架的概念,很长一段时间我都理解不了。Dos时代,都是对函数库的调用,你的程序主动调用函数。Windows时代,则换成了框架。就算是你的main程序,其实也是被框架调用的。UI线程会从操作系统获取消息,然后发送给你的程序来处理。Java程序员熟悉的Spring框架,也是这样一个反向调用的框架。
    现在因为“框架”这个术语显得很高大上,因此很多“类库”/“函数库”都自称为“框架”。在我看来这都是名称的滥用。
    “类库”/“函数库”就是我写的代码调用它们。
    “框架”就是我注册回调函数到框架,框架来调用我写的函数。
    另一个坎就是面向对象。很长一段时间我都不知道应该怎么设计类和类之间的关系,不能很好的设计出类层次结构来。
    我记得当时看到一本外国大牛的书,他讲了一个很简单、很实用的面向对象设计技巧:“叙述问题。然后把其中的名词找出来,用来构建类。把其中的动词找出来,用来构建类的方法”。虽然这个技巧挺管用的,但也太草根了点,没有理论依据,也不严谨。如果问题叙述的不好,那么获得的类系统就会是有问题的。
    掌握面向对象思想的途径应该有很多种,我是从关系数据库中获得了灵感来理解和掌握面向对象设计思想的。
    在我看来,关系数据库的表,其实就是一个类,每一行记录就是一个类的实例,也就是对象。表之间的关系,就是类之间的关系。O-Rmapping技术(如Hibernate),用于从面向对象代码到数据库表之间的映射,这也说明了类和表确实是逻辑上等价的。
    既然数据库设计和类设计是等价的,那么要设计面向对象系统,只需要使用关系数据库的设计技巧即可。
    关系数据库表结构设计是很简单的:
    1,识别表和表之间的关系,也就是类和类之间的关系。是一对一,一对多,多对一,还是多对多。这就是类之间的关系。
    2,识别表的字段。一个对象当然有无数多的属性(如,人:身高,体重,性别,年龄,姓名,身份证号,驾驶证号,银行卡号,护照号,港澳通行证号,工号,病史,婚史etc),我们写程序需要记录的只是我们关心的属性。这些关心的属性,就是表的字段,也就是类的属性。“弱水三千,我取一瓢饮”!

    4段—设计模式:
    曾经在网上看到这样一句话:“没有十万行代码量,就不要跟我谈什么设计模式”。深以为然。
    记得第一次看Gof的设计模式那本书的时候,发现虽然以前并不知道设计模式,但在实际编程过程中,其实还是自觉使用了一些设计模式。设计模式是编程的客观规律,不是谁发明的,而是一些早期的资深程序员首先发现的。
    不用设计模式,你也可以写出满足需求的程序来。但是,一旦后续需求变化,那么你的程序没有足够的柔韧性,将难以为继。而真实的程序,交付客户后,一定会有进一步的需求反馈。而后续版本的开发,也一定会增加需求。这是程序员无法回避的现实。
    写UI程序,不论是Web,Desktop,Mobile,Game,一定要使用MVC设计模式。否则你的程序面对后续变化的UI需求,将无以为继。
    设计模式,最重要的思想就是解耦,通过接口来解耦。这样,如果将来需求变化,那么只需要提供一个新的实现类即可。
    主要的设计模式,其实都是面向对象的。因此,可以认为设计模式是面向对象的高级阶段。只有掌握了设计模式,才能认为是真正彻底掌握了面向对象设计技巧。
    我学习一门新语言时(包括非面向对象语言,如函数式编程语言),总是会在了解了其语法后,看一下各类设计模式在这门语言中是如何实现的。这也是学习编程语言的一个窍门。

    5段–语言专家:

    经过一段时间的编程实践,程序员对某一种常用的编程语言已经相当精通了。有些人还成了“语言律师”,擅长向其他程序员讲解语言的用法和各种坑。
    这一阶段的程序员,常常是自己所用语言的忠实信徒,常在社区和论坛上和其他语言的使用者争论哪一种语言是最好的编程语言。他们认为自己所用的语言是世界上最好的编程语言,没有之一。他们认为,自己所用的编程语言适用于所有场景。他们眼中,只有锤子,因此会把所有任务都当成是钉子。

    6段–多语言专家:

    这一个阶段的程序员,因为工作关系,或者纯粹是因为对技术的兴趣,已经学习和掌握了好几种编程语言。已经领略了不同编程语言不同的设计思路,对每种语言的长处和短处有了更多的了解。
    他们现在认为,编程语言并不是最重要的,编程语言不过是基本功而已。
    他们现在会根据不同的任务需求,或者不同的资源来选择不同的编程语言来解决问题,不再会因为没有使用某一种喜爱的编程语言开发而埋怨。
    编程语言有很多种流派和思想,有一些编程语言同时支持多种编程范式。

    静态类型编程范式

    采用静态类型编程范式的编程语言,其变量需要明确指定类型。代表语言:C,C++,Pascal,Objective-C,Java,C#,VB.NET,Swif,Golang。
    这样做的好处是:
    1,编译器可以在编译时就能找出类型错误。
    2,编译器编译时知道类型信息,就可以提高性能。
    这种范式认为,程序员肯定知道变量的类型,你丫要是不知道变量的类型,那你就别混了!编译时,程序会报错。
    Swift和Go语言都是静态类型编程语言,但它们都不需要明确指定类型,而是可以通过推断由编译器自动确定其类型。

    动态类型编程范式
    采用静态类型编程范式的编程语言,其变量不需要明确指定类型。任意变量,可以指向任意类型的对象。代表语言:Python,Ruby,JavaScript。
    动态类型的哲学可以用鸭子类型(英语:ducktyping)这个概念来概括。JamesWhitcombRiley提出的鸭子测试可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
    这种范式认为,程序员肯定知道变量的类型和它支持的方法和属性,你丫要是不知道变量的类型,那你就别混了!运行时程序会崩溃!程序崩溃怨谁?怨你自己呗,你不是合格的程序员!
    动态类型的好处是:
    不需要明确定义接口和抽象类型。只要一个类型支持需要的方法和属性,那么就OK。程序会相当灵活和简单。C++,Java,C#视之为命脉的接口/基类,在动态语言这里都视如无物!
    缺点是:
    1,如果类型不对,编译器也无法找到错误,而是运行时程序崩溃。
    2,因为编译器不知道变量的类型,因此无法优化性能。

    面向对象编程范式
    面向对象编程范式,从上世纪70年代末开始兴起。它支持类和类的实例作为封装代码的模块。代表语言:Smalltalk,C++,Objective-C,Java,C#,VB.NET,Swift,Go,Python,Ruby,ActionScritp,OCaml.
    早期编程语言都是面向过程的。就是顺序,条件,循环,构成一个个函数。随着代码规模的增大,人们发现有必要对代码进行模块化。一个概念对应的代码放在一个文件中,这样便于并发开发和进行代码管理。
    人们还发现了“程序=数据结构+算法”的规律。因此,一个概念对应的数据结构和函数应该放在一个文件中。这就是类的概念。
    面向对象编程范式,确实极大地提高了生产效率,因此得到了广泛的应用,因此在语言层面支持面向对象编程范式的语言是极多的。
    C语言尽管在语言层面上并不支持面向对象编程范式,但现代的C语言开发都会应用面向对象的模块化思想,把同一类的数据结构和函数放在一个文件中,采用类似的命名方式。
    毕竟C语言没有在语言层面上支持面向对象,因此就有很多程序员想给C语言添加面向对象支持。其中的代表是C++和Objective-C。
    C++是一种新的语言,但大部分语言元素是和C兼容的。
    Objective-C是完全兼容的C的。Objective-C是给C添加了薄薄的一层语法糖以支持接口(就是其他语言的类)和协议(就是其他语言的接口)。甚至,Objective-C一开始的实现,就是一个C语言的预编译器。Objective-C坦白讲,除了添加的语法不太符合C流外,实际上其面向对象系统设计是相当精妙的。乔布斯早年慧眼识珠,把Objective-C收人囊中,因为封闭于Apple/NextStep系统内,因此少有人知。随着iOs系统的普及,Objective-C近几年才名满天下。

    函数式编程范式
    函数式编程范式,是一些数学家发明的编程语言,他们认为程序就是数学函数嘛。代表语言:Lisp,Erlang,JavaScript,OCaml,Prog。
    有很多大牛极力鼓吹过函数式编程语言,认为其极具革命性。但我认为他们过高估计了函数式编程范式的威力,我并不认为函数式编程范式相对于面向对象编程范式有何高明之处。
    函数式编程语言,核心就是函数,它们没有Class类的概念。但它的函数又不是传统面向过程语言的函数,它的函数支持“闭包”的概念。
    在我看来,函数式编程语言的函数,也就是“闭包”,说白了,其实就是“类”。编程语言发展到今天,就是需要模块化,就是需要把“数据结构”和“算法”结合起来。不论何种语言,不把它们结合起来的编程方式,都是没有出路的。
    面向对象编程语言,用类把“数据结构”和“算法”结合起来。类的核心是“数据结构”,也就是其“属性”,而不是“算法”,其“函数”。在类中,是函数依附于属性。
    而函数式编程语言,用闭包把“数据结构”和“算法”结合起来。是函数能够抓取外部的字段。是“属性”依附于“函数”。
    “类”本质上和“闭包”是等价的。现在很多面向对象编程语言都加上了对闭包的支持。观察其代码,我们可以发现,它们实际上都是用“类”来实现“闭包”的。
    “类”和“闭包”谁更易用?明显是“类”。
    而“闭包”更简洁一些,因此“闭包”在面向对象编程语言中常用来替换匿名类。只有一个函数的类,写成一个类太麻烦,不如写成闭包,更加简洁。
    吐槽一下OCaml语言,其前身Caml语言本身是一种挺好的函数式语言,硬生生添加了一套完整的面向对象机制,同时支持面向对象和函数式编程范式,很容易像C++一样脑裂的。
    也有很多面向对象语言控看着JavaScript嫌烦,总是想把面向对象支持添加到JavaScript上。ActionScript就是其中一种尝试。我用过,真的是和Java没多少区别了。
    再吐槽一下ExtJS。当初选型Web前端开发框架时比较了ExtJS和JQuery。
    ExtJS明显是Java高手开发的,硬生生用JavaScript模拟Swing的设计思想,搞了一套UI库。
    JQuery开发者明显是领悟了JavaScript的函数式编程范式,依据JavaScript的动态函数式编程语言的特点打造了一套UI库,立刻秒杀ExtJS。
    由ExtJS和JQuery的故事,我们可以看到多语言编程能力是多么的重要。ExtJS的作者精通并喜爱Java,因此他把手术刀JavaScript当做锤子Java使,一通乱敲,费力不讨好。
    函数式编程语言,还有尾递归等一些小技巧。尾递归可以不用栈,防止递归调用时栈溢出。

    模板编程范式
    模板编程,就是把类型作为参数,一套函数可以支持任意多种类型。代表语言:C++。
    模板编程的需求,是在C++开发容器库的时候发明的。因为容器需要保存任意类型的对象,因此就有了泛型的需求。
    C++的模板编程,是在编译时,根据源码中的使用情况,创建对应类型的代码。除了C++这种方式,Java,C#也有类似的机制,叫做“泛型”,但它们的实现方式和C++的模板很不同。它们的编译器不会生成新的代码,而是使用强制类型转换的方式实现。
    在没有模板/泛型的编程语言中,怎样在容器中存放对象呢?存取公共基类类型(Java,C#)的对象,或者void*指针(C)即可,取出时自己强制类型转换为实际类型。动态类型语言,不关心类型,更是无所谓了,随便什么对象直接往容器里扔进去,取出来直接用即可。
    一些C++高手又在模板的基础上搞出了“模板元编程”。因为模板编程,就是C++的编译器搞定的嘛,模板元编程就是让编译器运算,编译完结果也就算出来了。我不知道除了研究和炫技,这玩意有啥用?

    小结
    一门语言是否值得学习,我认为有几个标准:
    1,是否要用,要用就得学,这么没有疑问的。毕竟我们都要吃饭的嘛。
    2,其语言特性是否给你耳目一新的感觉。如果是,那就值回票价了。如Go语言废掉了异常,改用返回多值。我深以为然。我其实已经主动不用异常好多年了。因为,我觉得既然C不支持异常也活得很好,为什么需要异常呢?出错了,返回错误码。无法挽回的错误,直接Abort程序就可以嘛!而且,异常实际上是违反面向过程编程原则的。一个函数应该只有一个入口一个出口。抛出异常就多了出口了。
    3,是否擅长某一个领域。如果你手里只有一把锤子,那么你就只能把所有任务都当做钉子猛锤一通。但如果工具箱里有多种工具,那面对不同的任务就得心应手多了。

    7段—架构设计
    还需要掌握架构设计的能力,才能设计出优秀的软件。架构设计有一些技巧:
    1,分层
    一个软件通常分为:
    表现层–UI部分
    接口层–后台服务的通讯接口部分
    服务层–实际服务部分
    存储层—持久化存储部分,存储到文件或者数据库。
    分层的软件,可以解耦各个模块,支持并行开发,易于修改,易于提升性能。
    2,SOA
    模块之间通过网络通讯互相连接,松耦合。每一个模块可以独立部署,可以增加部署实例从而提高性能。每一个模块可以使用不同的语言和平台开发,可以重用之前开发的服务。SOA,常用协议有WebService,REST,JSON-RPC等。
    3,性能瓶颈
    1)化同步为异步。
    用内存队列(Redis),工作流引擎(JBpm)等实现。内存队列容易丢失数据,但是速度快。工作流引擎会把请求保存到数据库中。
    通过化同步请求为异步请求,基本上99.99%的性能问题都可以解决。
    2)用单机并行硬件处理。
    如,使用GPU,FPGA等硬件来处理,提高性能。
    3)用集群计算机来处理。
    如,Hadoop集群,用多台计算机来并行处理数据。
    自己的软件栈中,也可以把一个模块部署多份,并行处理。
    4)用cache来满足请求。常用的内容加热cache后,大量的用户请求都只是内存读取数据而已,性能会得到很大的提升。
    cache是上帝算法,记得好像它的性能只比最佳性能低一些,就好像你是上帝,能够预见未来一样。现在X86CPU遇到了主频限制,CPU提升性能的主要途径就是增加高速Cache了。
    4,大系统小做
    遇到大型系统不要慌,把它切分成多个模块,用多个小程序,通过SOA协作来解决。这秉承了Unix的设计思想。Unix上开发了大量单一目的的小程序,它主张用户通过管道来让多个小程序协作,解决用户的需求。当然,管道方式通讯限制太多,不够灵活。因此,现在我们可以通过URI,通过SOA的方式来让多个程序协作。Andorid和iOS上的应用程序,现在都是通过URI实现协作的。这也算是Unix设计思想的现代发展吧?!
    5,Sharding切片
    现在有一个潮流,就是去IOE。I-IBM大型机,O-Oracle数据库,E-EMC存储。之前,大型系统常用IOE去架构,在大型机上部署一个Oracle数据库,Oracle数据库用EMC存储保存数据。IOE是当今最强的计算机,数据库和存储。但他们面对海量系统也有抗不住的一天。
    Oracle数据库是Shareeverything的,它可以在一个计算机集群(服务器节点不能超过16个)上运行。计算机集群都共用一个存储。
    去IOE运动,标志着ShareEverything模式的破产。必须使用ShareNothing,系统才能无限扩展。
    用MySQL数据库就可以应付任意规模的数据了。前提是,你会Sharding分片。把大系统切分成若干个小系统,切分到若干台廉价服务器和存储上。更Modern一些,就是切分到大量虚拟机上。
    如,铁道部的12306网站。我们知道火车票都是从属于某一列列车的。那么我们把每一个列车作为一个单元来切分,就可以把12306网站切分成几千个模块。一台虚拟机可以承载若干个模块。当某些列车成为性能瓶颈之后,就可以把它们迁移到独立的虚拟机上。即使最终有部分列出服务不可用,系统也不会完全不可用。
    12306网站,只有一个全局的部分,就是用户登录。这个可以交给第三方负责。如可以让用户用微信,微博,qq等账户登录。
    也可以自己实现用户登录服务。还是用切片的方式用多台Redis服务器提供服务。Redis服务器存储每一个登录用户的sessionId和userId,角色,权限等信息。sessionId是随机生成的,可选择其部分bit用于标识它在哪一个Redis服务器上。用户登录后,把sessionId发给客户。用户每次请求时把sessionId发回给服务器。服务器把sessionId发给Redis服务器查询得到其用户信息,对用户请求进行处理。如果在redis服务器上找不到sessionId,则让用户去登录。即使所有注册用户同时登陆,也不需要太多的内存。而且,可以在session内存过多时,删除最早登陆的用户的session,强制他再次登陆。同时活跃的用户数不会太多。

    领域知识层次
    前面的所有层次,都是关注编程本身的技能,说白了,就是基本功,本身并不能产生太大的价值。但有太多的程序员浪费太多的时间在那些筑基的层次上。
    有些程序员特别喜欢钻研编程语言,每有一种新的编程语言出来或者旧语言被热炒,就会投入精力进去研究。我就是其中之一,浪费了很多精力在编程语言上,在奇技淫巧上。
    我觉得C++语言是一个特别大的坑。刚开始是作为面向对象的C被开发的。后来发现了模板编程,就大力鼓吹模板编程和进一步的模板元编程。最近又推出了C++11,C++14等新标准,进一步添加了很多新东西,函数式编程,类型推断等。C++过分复杂,太多的坑消耗了大量程序员的大量精力。我使用C++时,只使用面向对象部分和模板部分,其他过于精深的特性都不使用。
    计算机科学是一个面相当广泛的学科,有很多领域知识需要和值得我们深入研究,我们才能写出有价值的程序来。软件必须要和行业结合起来,要落地才有价值。仅仅研究编程技巧,不懂领域知识是写不出有价值的程序的。
    计算机科学领域有很多,列举一些如下:
    •存储—-块设备,文件系统,集群文件系统,分布式文件系统,光纤SCSI,iSCSI,RAID等。
    •网络—-以太网,光纤网,蜂窝网络,WIFI,VLAN等。
    •计算机体系结构,主要就是CPU指令集。x86,ARM等。
    •USB协议。需要知道URB包。
    •PCI协议,PCI-E协议。现代计算机的外设都是PCI协议和PCI-E协议的。显卡现在全是通过 PCI-E协议连接到计算机上的。相对来说减少了很多需要学习的知识。搞虚拟化就需要深入掌握PCI协议。
    •图像处理–图像压缩,视频实时编码等。
    •3D游戏
    •关系数据库
    •NoSQL数据库
    •操作系统
    •分布式操作系统
    •编译原理
    •机器学习–现在大数据要用哦!
    了解这些领域知识,也包括了解该领域现有的商用硬件、商用软件和开源软件。很多时候,你要完成的工作,已经有现成的工具了。你只要使用现成的工具就可以完成任务,不需要进行开发。有时候,只需要组合现有的工具,写一些脚本就可以完成任务。
    如,我一次要实现一个双向同步任务。找到了一个优秀的开源软件Unison,编写一下配置文件就圆满地完成了任务。不需要编写任何代码。
    还有一次,要做高可用,用Python调用了几个开源软件就轻松实现了。
    编写安装程序,定制操作系统,知道了操作系统的领域知识,写几行脚本就可以轻松搞定。
    不具备领域知识的人,就可能不得不进行大量无谓的开发,甚至开发很久之后才发现,这根本就是一条死路。
    另外,扎实的领域知识,可以大大提高编程调试、查错的能力。知道编译器和编程语言运行时工作原理,就能快速根据编译错误和警告信息修改代码。
    知道操作系统底层运行机制,就能快速找到运行时错误的问题根源。如,有一次我编写一个windows升级服务程序。它是一个windows服务,需要执行dos脚本,这个脚本会替换掉这个windows服务本身。发现有时脚本执行无效,查了一晚上,发现当windows服务安装后,第一次启动就执行脚本时就会有权限问题,log都正确,但实际执行这个脚本没有任何效果。但一旦windows服务程序启动一次之后就ok。这必然是windows操作系统底层安全机制的问题,因为我对Windows内核了解不多,因此花了很长时间才发现这个问题,并对造成这个问题的根源并不清楚。

    0段—领域知识菜鸟
    对领域知识没有多少认知,通过搜索引擎找到一些该领域的软件和硬件的介绍性文章,按照文章指示配置和使用软件。勉强能够使用现有软硬件。

    1段—领域知识行家
    了解领域内常用硬件,深入掌握领域内常用软件的配置和使用技巧。能够使用现有软硬件熟练搭建解决方案,能够解决实际工作中遇到的种种问题。

    2段—领域知识专家
    当你不仅仅掌握了该领域的软件和工具,知道怎么用,还知道其原理,“知其然,也知其所以然”,就是该领域的知识专家了。
    你知道网络协议的原理,你才能在网络出现问题时知道是哪里可能出现了问题。是mac冲突,ip冲突,还是网络环路?
    你知道存储的原理,你才能知道为什么这种存储方式不适合虚拟化,那种存储方式适合虚拟化,另一种方式适合资料备份。
    你知道PCI协议,你才能知道你怎样才能虚拟化一个硬件设备。
    你知道网卡硬件协议,你才能模拟出一个虚拟机能正常使用的虚拟网卡。
    你知道视频编码格式和原理,才能知道什么视频格式占用带宽最少,什么视频格式占用CPU最少。
    你了解IntelVT/Amd V指令集,才能知道虚拟化是怎样实现的。
    你明白工作流其实就是状态机,在遇到复杂工作流程时,你才能知道怎样设计满足要求的工作流引擎。

    3段—科学家
    你是领域知识专家,但你的知识都是来自于书本,来自于其他人的。
    如果你满足于当领域知识专家,你只能拾人牙慧,永远别想超越。别人的研究成果,未必愿意告诉你。当别人告诉你的时候,它可能已经发现了更新的理论,并且新一代产品可能马上就要发布了。
    科学家是探索未知,勇于创新的人,是推动人类社会进步的人。
    传说,思科的一位高管曾经半开玩笑地说过:“如果思科停止了新技术的研发,华为就会找不着方向”。这是在嘲笑华为只是处在领域知识专家的水平,只能山寨无法超越。我不知道华为的实际情况,但希望现在的华为已经走到了领跑者的位置。
    欧文·雅各布斯发现了CDMA码分多址的原理,并发现它在通讯上大有可为,组建了高通公司。高通公司主要以专利授权费为生,它雇佣了大量科学家在通讯领域展开研究。有人说高通是专利流氓。这些人不明白知识的价值。在他们眼里,Windows的合理价格就应该是5元钱,一张光盘的价格。iPhone就应该是1000多元裸机的价格。高通是专利流氓,那你也流氓一个CDMA,LTE出来给我看看!
    X86芯片在设计上没有考虑虚拟化。因此会有所谓的“虚拟化漏洞”出现。就是说,一些CPU特权指令执行时,在虚拟机环境下不会抛出异常,因此就无法切换到Host。这样,X86芯片上就无法运行虚拟机。
    VmWare公司是由美国的几位科学家在1998年创建的。他们发现可以使用二进制翻译的技术,在X86计算机上运行虚拟机。
    Xen虚拟化软件也是几位科学家发明的。他们发现只要修改虚拟机操作系统和Host操作系统的内核,在需要执行“虚拟化漏洞”指令时直接调用Host的功能,就可以实现虚拟化,而且大大提高了虚拟机的运行性能。
    后来,Intel为自己的芯片添加了IntelVT指令集,Amd为自己的芯片添加了AmdV指令集,弥补了“虚拟化漏洞”。于是就有了KVM虚拟机软件,它直接用CPU硬件指令实现虚拟化。
    KVM在执行CPU指令时,是直接在物理CPU上运行的,因此效率极高。但是,虚拟机运行虚拟外设时,就必须用软件模拟,因此虚拟机的IO访问速度很慢。
    IBM科学家RustyRussell,借鉴了Xen的研发经验,创建了VirtIO技术。就是在虚拟机中编写一套PCI虚拟设备和驱动,这套虚拟PCI设备有一块虚拟设备内存。这个虚拟设备内存Host是可以访问的,虚拟机通过VirtIO驱动程序也可以访问。也就是一块内存在虚拟机和Host中共享,这就解决了虚拟机的IO性能问题。
    再讲一个搜索引擎的故事:
    很久以前,我要给一个程序添加搜索功能。刚开始使用sql查询实现,发现实在太慢了。后来找了开源的Lucene项目。它使用反向索引技术,通过在文件中创建反向索引,大大提高了搜索速度。
    Google的两位创始人发现了html中link的秘密,他们发现可以通过html页面的link关系来为每一个html页面设置权重。也就是PageRank算法。于是,Google的自动搜索引擎击败了Yahoo人工分类的搜索引擎。
    OK,利用反向索引技术和PageRank,以及一个简单的html爬虫机器人,我们就可以创建一个搜索引擎了。但是,互联网很大,每天产生大量新网页,要为整个互联网建立反向索引是很困难的。
    若干年后Google又公开了三篇论文:Googlefs,Mapreduce,Bigtable。于是Lucene项目的开发者根据Google的Mapreduce论文开发了Hadoop项目。MapReduce就是使用大量计算机存储数据并计算,最后汇总结果。使用Hadoop+反向索引+PageRank,就可以创建搜索引擎了。Yahoo,Baidu等公司纷纷基于Hadoop开发了自己的搜索引擎。
    但是,其他公司的搜索引擎效果还是没法和Google相比。这一点我们程序员最清楚。像我,就总是翻墙出去,只为了Google一下。
    Google黑板报上发表了吴军博士的一些文章,其中介绍了很多机器学习方面的知识。从文中可以知道,Google其实使用机器学习来分析搜集到的页面。Google明显不会把这个公式公开出来。即使有一天Google真的公开了这个公式,那么可以想见Google肯定又研发出了更加犀利的秘籍,山寨货的搜索引擎效果还是比不上Google的。
    山寨是通向创新的必由之路。在成为领域的领头羊和领导者之前,必然要经过学习,模仿的阶段。但要成为行业的老大,成为Champion,必须勇于弯道超车,勇敢地走上创新之路,成为真正的科学家,真正的大牛!

    总结
    编程能力可分为两个维度:一个是编程技能水平,另一个是领域知识水平。
    有些程序员可能把精力都花在提升编程技能上了,领域知识知之甚少,这其实在日常工作中也是极其有害的。有些需求可能早已经有了现成、开源免费的解决方案,或者只需要组合几个现有软件就可以快速搞定,而他们却不得不自己花大量时间去开发。另外,缺少领域知识,在程序出现非预期状况时,很难快速定位到问题的根源,很难解决bug。

    展开全文
  • 编程能力层次模型

    千次阅读 2016-02-20 13:04:48
     下面通过两个维度展开编程能力层次模型的讨论。  一个维度是编程技能层次,另一个维度是领域知识层次。 编程技能层次  编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本。 ...

    前言

           程序员的编程技能随着经验的积累,会逐步提高。我认为编程能力可以分为一些层次。

          下面通过两个维度展开编程能力层次模型的讨论。

          一个维度是编程技能层次,另一个维度是领域知识层次。


    编程技能层次

            编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本。



    0非程序员:

           初学编程者,遇到问题,完全是懵懵懂懂,不知道该怎么编程解决问题。也就是说,还是门外汉,还不能称之为程序员。计算机在他面前还是一个神秘的黑匣子。



    1基础程序员:

           学习过一段时间编程后,接到任务,可以编写程序完成任务。

          编写出来的代码,正常情况下是能够工作的,但在实际运行中,碰到一些特殊条件就会出现各类BUG。也就是说,具备了开发Demo软件的能力,但开发的软件真正交付给客户使用,恐怕会被客户骂死。

          程序员程序是写好了,但到底为什么它有时能正常工作,有时又不行,程序员自己也不知道。

         运行中遇到了bug,或者需求改变,需要修改代码或者添加代码,很快程序就变得结构混乱,代码膨胀,bug丛生。很快,就连最初的开发者自己也不愿意接手维护这个程序了。



    2数据结构:

           经过一段时间的编程实践后,程序员会认识到数据结构+算法=程序这一古训的含义。他们会使用算法来解决问题。进而,他们会认识到,算法本质上是依附于数据结构的,好的数据结构一旦设计出来,那么好的算法也会应运而生。

          设计错误的数据结构,不可能生长出好的算法。

          记得某一位外国先贤曾经说过:给我看你的数据结构!



    3面向对象:

             再之后,程序员就会领略面向对象程序设计的强大威力。大多数现代编程语言都是支持面向对象的。但并不是说,你使用面向对象编程语言编程,你用上了类,甚至继承了类,你就是在写面向对象的代码了。

           我曾经见过很多用Java,Python,Ruby写的面向过程的代码。

          只有你掌握了接口,掌握了多态,掌握了类和类,对象和对象之间的关系,你才真正掌握了面向对象编程技术。

          就算你用的是传统的不支持面向对象的编程语言,只要你心中有对象,你依然可以开发出面向对象的程序。

           如,我用C语言编程的时候,会有意识的使用面向对象的技巧来编写和设计程序。用struct来模拟类,把同一类概念的函数放在一起模拟类。如果你怀疑用C语言是否能编写出面向对象的代码,你可以看一下Linux内核,它是用C语言编写的,但你也可以看到它的源代码字里行间散发出的浓浓的对象的味道。


          真正掌握面向对象编程技术并不容易。



           在我的技术生涯中,有两个坎让我最感头疼。

           一个坎是DosWindows开发的变迁过程中,框架的概念,很长一段时间我都理解不了。Dos时代,都是对函数库的调用,你的程序主动调用函数。Windows时代,则换成了框架。就算是你的main程序,其实也是被框架调用的。UI线程会从操作系统获取消息,然后发送给你的程序来处理。Java程序员熟悉的Spring框架,也是这样一个反向调用的框架。

          现在因为框架这个术语显得很高大上,因此很多类库/“函数库都自称为框架。在我看来这都是名称的滥用。

          “类库/“函数库就是我写的代码调用它们。

          “框架就是我注册回调函数到框架,框架来调用我写的函数。



          另一个坎就是面向对象。很长一段时间我都不知道应该怎么设计类和类之间的关系,不能很好的设计出类层次结构来。

          我记得当时看到一本外国大牛的书,他讲了一个很简单、很实用的面向对象设计技巧:叙述问题。然后把其中的名词找出来,用来构建类。把其中的动词找出来,用来构建类的方法。虽然这个技巧挺管用的,但也太草根了点,没有理论依据,也不严谨。如果问题叙述的不好,那么获得的类系统就会是有问题的。



            掌握面向对象思想的途径应该有很多种,我是从关系数据库中获得了灵感来理解和掌握面向对象设计思想的。

           在我看来,关系数据库的表,其实就是一个类,每一行记录就是一个类的实例,也就是对象。表之间的关系,就是类之间的关系。O-Rmapping技术(如Hibernate),用于从面向对象代码到数据库表之间的映射,这也说明了类和表确实是逻辑上等价的。

           既然数据库设计和类设计是等价的,那么要设计面向对象系统,只需要使用关系数据库的设计技巧即可。

    关系数据库表结构设计是很简单的:

    1,识别表和表之间的关系,也就是类和类之间的关系。是一对一,一对多,多对一,还是多对多。这就是类之间的关系。

    2,识别表的字段。一个对象当然有无数多的属性(如,人:身高,体重,性别,年龄,姓名,身份证号,驾驶证号,银行卡号,护照号,港澳通行证号,工号,病史,婚史etc),我们写程序需要记录的只是我们关心的属性。这些关心的属性,就是表的字段,也就是类的属性。弱水三千,我取一瓢饮


    4设计模式:

           曾经在网上看到这样一句话:没有十万行代码量,就不要跟我谈什么设计模式。深以为然。

           记得第一次看Gof的设计模式那本书的时候,发现虽然以前并不知道设计模式,但在实际编程过程中,其实还是自觉使用了一些设计模式。设计模式是编程的客观规律,不是谁发明的,而是一些早期的资深程序员首先发现的。

          不用设计模式,你也可以写出满足需求的程序来。但是,一旦后续需求变化,那么你的程序没有足够的柔韧性,将难以为继。而真实的程序,交付客户后,一定会有进一步的需求反馈。而后续版本的开发,也一定会增加需求。这是程序员无法回避的现实。



         UI程序,不论是Web,Desktop,Mobile,Game,一定要使用MVC设计模式。否则你的程序面对后续变化的UI需求,将无以为继。



          设计模式,最重要的思想就是解耦,通过接口来解耦。这样,如果将来需求变化,那么只需要提供一个新的实现类即可。

           主要的设计模式,其实都是面向对象的。因此,可以认为设计模式是面向对象的高级阶段。只有掌握了设计模式,才能认为是真正彻底掌握了面向对象设计技巧。



          我学习一门新语言时(包括非面向对象语言,如函数式编程语言),总是会在了解了其语法后,看一下各类设计模式在这门语言中是如何实现的。这也是学习编程语言的一个窍门。


    5--语言专家:

            经过一段时间的编程实践,程序员对某一种常用的编程语言已经相当精通了。有些人还成了语言律师,擅长向其他程序员讲解语言的用法和各种坑。

            这一阶段的程序员,常常是自己所用语言的忠实信徒,常在社区和论坛上和其他语言的使用者争论哪一种语言是最好的编程语言。他们认为自己所用的语言是世界上最好的编程语言,没有之一。他们认为,自己所用的编程语言适用于所有场景。他们眼中,只有锤子,因此会把所有任务都当成是钉子。



    6--多语言专家:

            这一个阶段的程序员,因为工作关系,或者纯粹是因为对技术的兴趣,已经学习和掌握了好几种编程语言。已经领略了不同编程语言不同的设计思路,对每种语言的长处和短处有了更多的了解。

           他们现在认为,编程语言并不是最重要的,编程语言不过是基本功而已。

           他们现在会根据不同的任务需求,或者不同的资源来选择不同的编程语言来解决问题,不再会因为没有使用某一种喜爱的编程语言开发而埋怨。



           编程语言有很多种流派和思想,有一些编程语言同时支持多种编程范式。


    静态类型编程范式

          采用静态类型编程范式的编程语言,其变量需要明确指定类型。代表语言:C,C++,Pascal,Objective-C,Java,C#,VB.NET,Swif,Golang

    这样做的好处是:

    1,编译器可以在编译时就能找出类型错误。

    2,编译器编译时知道类型信息,就可以提高性能。

             这种范式认为,程序员肯定知道变量的类型,你丫要是不知道变量的类型,那你就别混了!编译时,程序会报错。

            SwiftGo语言都是静态类型编程语言,但它们都不需要明确指定类型,而是可以通过推断由编译器自动确定其类型。


    动态类型编程范式

             采用静态类型编程范式的编程语言,其变量不需要明确指定类型。任意变量,可以指向任意类型的对象。代表语言:Python,Ruby,JavaScript

            动态类型的哲学可以用鸭子类型(英语:ducktyping)这个概念来概括。JamesWhitcombRiley提出的鸭子测试可以这样表述:当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

           这种范式认为,程序员肯定知道变量的类型和它支持的方法和属性,你丫要是不知道变量的类型,那你就别混了!运行时程序会崩溃!程序崩溃怨谁?怨你自己呗,你不是合格的程序员!


    动态类型的好处是:

          不需要明确定义接口和抽象类型。只要一个类型支持需要的方法和属性,那么就OK。程序会相当灵活和简单。C++,Java,C#视之为命脉的接口/基类,在动态语言这里都视如无物!


    缺点是:

    1,如果类型不对,编译器也无法找到错误,而是运行时程序崩溃。

    2,因为编译器不知道变量的类型,因此无法优化性能。



    面向对象编程范式

            面向对象编程范式,从上世纪70年代末开始兴起。它支持类和类的实例作为封装代码的模块。代表语言:Smalltalk,C++,Objective-C,Java,C#,VB.NET,Swift,Go,Python,Ruby,ActionScritp,OCaml.

           早期编程语言都是面向过程的。就是顺序,条件,循环,构成一个个函数。随着代码规模的增大,人们发现有必要对代码进行模块化。一个概念对应的代码放在一个文件中,这样便于并发开发和进行代码管理。

           人们还发现了程序=数据结构+算法的规律。因此,一个概念对应的数据结构和函数应该放在一个文件中。这就是类的概念。

           面向对象编程范式,确实极大地提高了生产效率,因此得到了广泛的应用,因此在语言层面支持面向对象编程范式的语言是极多的。

           C语言尽管在语言层面上并不支持面向对象编程范式,但现代的C语言开发都会应用面向对象的模块化思想,把同一类的数据结构和函数放在一个文件中,采用类似的命名方式。

           毕竟C语言没有在语言层面上支持面向对象,因此就有很多程序员想给C语言添加面向对象支持。其中的代表是C++Objective-C

          C++是一种新的语言,但大部分语言元素是和C兼容的。

          Objective-C是完全兼容的C的。Objective-C是给C添加了薄薄的一层语法糖以支持接口(就是其他语言的类)和协议(就是其他语言的接口)。甚至,Objective-C一开始的实现,就是一个C语言的预编译器。Objective-C坦白讲,除了添加的语法不太符合C流外,实际上其面向对象系统设计是相当精妙的。乔布斯早年慧眼识珠,把Objective-C收人囊中,因为封闭于Apple/NextStep系统内,因此少有人知。随着iOs系统的普及,Objective-C近几年才名满天下。



    函数式编程范式

             函数式编程范式,是一些数学家发明的编程语言,他们认为程序就是数学函数嘛。代表语言:Lisp,Erlang,JavaScript,OCaml,Prog

             有很多大牛极力鼓吹过函数式编程语言,认为其极具革命性。但我认为他们过高估计了函数式编程范式的威力,我并不认为函数式编程范式相对于面向对象编程范式有何高明之处。

            函数式编程语言,核心就是函数,它们没有Class类的概念。但它的函数又不是传统面向过程语言的函数,它的函数支持闭包的概念。

           在我看来,函数式编程语言的函数,也就是闭包,说白了,其实就是。编程语言发展到今天,就是需要模块化,就是需要把数据结构算法结合起来。不论何种语言,不把它们结合起来的编程方式,都是没有出路的。

            面向对象编程语言,用类把数据结构算法结合起来。类的核心是数据结构,也就是其属性,而不是算法,其函数。在类中,是函数依附于属性。

            而函数式编程语言,用闭包把数据结构算法结合起来。是函数能够抓取外部的字段。是属性依附于函数

           “本质上和闭包是等价的。现在很多面向对象编程语言都加上了对闭包的支持。观察其代码,我们可以发现,它们实际上都是用来实现闭包的。

           “闭包谁更易用?明显是

           闭包更简洁一些,因此闭包在面向对象编程语言中常用来替换匿名类。只有一个函数的类,写成一个类太麻烦,不如写成闭包,更加简洁。



             吐槽一下OCaml语言,其前身Caml语言本身是一种挺好的函数式语言,硬生生添加了一套完整的面向对象机制,同时支持面向对象和函数式编程范式,很容易像C++一样脑裂的。

           也有很多面向对象语言控看着JavaScript嫌烦,总是想把面向对象支持添加到JavaScript上。ActionScript就是其中一种尝试。我用过,真的是和Java没多少区别了。


           再吐槽一下ExtJS。当初选型Web前端开发框架时比较了ExtJSJQuery

           ExtJS明显是Java高手开发的,硬生生用JavaScript模拟Swing的设计思想,搞了一套UI库。

           JQuery开发者明显是领悟了JavaScript的函数式编程范式,依据JavaScript的动态函数式编程语言的特点打造了一套UI库,立刻秒杀ExtJS

           ExtJSJQuery的故事,我们可以看到多语言编程能力是多么的重要。ExtJS的作者精通并喜爱Java,因此他把手术刀JavaScript当做锤子Java使,一通乱敲,费力不讨好。


           函数式编程语言,还有尾递归等一些小技巧。尾递归可以不用栈,防止递归调用时栈溢出。



    模板编程范式

            模板编程,就是把类型作为参数,一套函数可以支持任意多种类型。代表语言:C++

           模板编程的需求,是在C++开发容器库的时候发明的。因为容器需要保存任意类型的对象,因此就有了泛型的需求。

             C++的模板编程,是在编译时,根据源码中的使用情况,创建对应类型的代码。除了C++这种方式,JavaC#也有类似的机制,叫做泛型,但它们的实现方式和C++的模板很不同。它们的编译器不会生成新的代码,而是使用强制类型转换的方式实现。

           在没有模板/泛型的编程语言中,怎样在容器中存放对象呢?存取公共基类类型(Java,C#)的对象,或者void*指针(C)即可,取出时自己强制类型转换为实际类型。动态类型语言,不关心类型,更是无所谓了,随便什么对象直接往容器里扔进去,取出来直接用即可。

          一些C++高手又在模板的基础上搞出了模板元编程。因为模板编程,就是C++的编译器搞定的嘛,模板元编程就是让编译器运算,编译完结果也就算出来了。我不知道除了研究和炫技,这玩意有啥用?



    小结

             一门语言是否值得学习,我认为有几个标准:

    1,是否要用,要用就得学,这么没有疑问的。毕竟我们都要吃饭的嘛。

    2,其语言特性是否给你耳目一新的感觉。如果是,那就值回票价了。如Go语言废掉了异常,改用返回多值。我深以为然。我其实已经主动不用异常好多年了。因为,我觉得既然C不支持异常也活得很好,为什么需要异常呢?出错了,返回错误码。无法挽回的错误,直接Abort程序就可以嘛!而且,异常实际上是违反面向过程编程原则的。一个函数应该只有一个入口一个出口。抛出异常就多了出口了。

    3,是否擅长某一个领域。如果你手里只有一把锤子,那么你就只能把所有任务都当做钉子猛锤一通。但如果工具箱里有多种工具,那面对不同的任务就得心应手多了。




    7架构设计

            还需要掌握架构设计的能力,才能设计出优秀的软件。架构设计有一些技巧:

    1,分层

            一个软件通常分为:

    表现层--UI部分

    接口层--后台服务的通讯接口部分

    服务层--实际服务部分

    存储层持久化存储部分,存储到文件或者数据库。


            分层的软件,可以解耦各个模块,支持并行开发,易于修改,易于提升性能。



    2SOA

             模块之间通过网络通讯互相连接,松耦合。每一个模块可以独立部署,可以增加部署实例从而提高性能。每一个模块可以使用不同的语言和平台开发,可以重用之前开发的服务。SOA,常用协议有WebService,REST,JSON-RPC等。



    3,性能瓶颈

    1)化同步为异步。

         用内存队列(Redis),工作流引擎(JBpm)等实现。内存队列容易丢失数据,但是速度快。工作流引擎会把请求保存到数据库中。

         通过化同步请求为异步请求,基本上99.99%的性能问题都可以解决。



    2)用单机并行硬件处理。

         如,使用GPUFPGA等硬件来处理,提高性能。



    3)用集群计算机来处理。

         如,Hadoop集群,用多台计算机来并行处理数据。

         自己的软件栈中,也可以把一个模块部署多份,并行处理。



    4)用cache来满足请求。常用的内容加热cache后,大量的用户请求都只是内存读取数据而已,性能会得到很大的提升。

          cache是上帝算法,记得好像它的性能只比最佳性能低一些,就好像你是上帝,能够预见未来一样。现在X86CPU遇到了主频限制,CPU提升性能的主要途径就是增加高速Cache了。



    4,大系统小做

           遇到大型系统不要慌,把它切分成多个模块,用多个小程序,通过SOA协作来解决。这秉承了Unix的设计思想。Unix上开发了大量单一目的的小程序,它主张用户通过管道来让多个小程序协作,解决用户的需求。当然,管道方式通讯限制太多,不够灵活。因此,现在我们可以通过URI,通过SOA的方式来让多个程序协作。AndoridiOS上的应用程序,现在都是通过URI实现协作的。这也算是Unix设计思想的现代发展吧?!



    5Sharding切片

            现在有一个潮流,就是去IOEI-IBM大型机,O-Oracle数据库,E-EMC存储。之前,大型系统常用IOE去架构,在大型机上部署一个Oracle数据库,Oracle数据库用EMC存储保存数据。IOE是当今最强的计算机,数据库和存储。但他们面对海量系统也有抗不住的一天。


            Oracle数据库是Shareeverything的,它可以在一个计算机集群(服务器节点不能超过16个)上运行。计算机集群都共用一个存储。

            IOE运动,标志着ShareEverything模式的破产。必须使用ShareNothing,系统才能无限扩展。

             MySQL数据库就可以应付任意规模的数据了。前提是,你会Sharding分片。把大系统切分成若干个小系统,切分到若干台廉价服务器和存储上。更Modern一些,就是切分到大量虚拟机上。


              如,铁道部的12306网站。我们知道火车票都是从属于某一列列车的。那么我们把每一个列车作为一个单元来切分,就可以把12306网站切分成几千个模块。一台虚拟机可以承载若干个模块。当某些列车成为性能瓶颈之后,就可以把它们迁移到独立的虚拟机上。即使最终有部分列出服务不可用,系统也不会完全不可用。


             12306网站,只有一个全局的部分,就是用户登录。这个可以交给第三方负责。如可以让用户用微信,微博,qq等账户登录。


             也可以自己实现用户登录服务。还是用切片的方式用多台Redis服务器提供服务。Redis服务器存储每一个登录用户的sessionIduserId,角色,权限等信息。sessionId是随机生成的,可选择其部分bit用于标识它在哪一个Redis服务器上。用户登录后,把sessionId发给客户。用户每次请求时把sessionId发回给服务器。服务器把sessionId发给Redis服务器查询得到其用户信息,对用户请求进行处理。如果在redis服务器上找不到sessionId,则让用户去登录。即使所有注册用户同时登陆,也不需要太多的内存。而且,可以在session内存过多时,删除最早登陆的用户的session,强制他再次登陆。同时活跃的用户数不会太多。






    领域知识层次

             前面的所有层次,都是关注编程本身的技能,说白了,就是基本功,本身并不能产生太大的价值。但有太多的程序员浪费太多的时间在那些筑基的层次上。

            有些程序员特别喜欢钻研编程语言,每有一种新的编程语言出来或者旧语言被热炒,就会投入精力进去研究。我就是其中之一,浪费了很多精力在编程语言上,在奇技淫巧上。

            我觉得C++语言是一个特别大的坑。刚开始是作为面向对象的C被开发的。后来发现了模板编程,就大力鼓吹模板编程和进一步的模板元编程。最近又推出了C++11C++14等新标准,进一步添加了很多新东西,函数式编程,类型推断等。C++过分复杂,太多的坑消耗了大量程序员的大量精力。我使用C++时,只使用面向对象部分和模板部分,其他过于精深的特性都不使用。

           计算机科学是一个面相当广泛的学科,有很多领域知识需要和值得我们深入研究,我们才能写出有价值的程序来。软件必须要和行业结合起来,要落地才有价值。仅仅研究编程技巧,不懂领域知识是写不出有价值的程序的。



    计算机科学领域有很多,列举一些如下:

    存储----块设备,文件系统,集群文件系统,分布式文件系统,光纤SCSIiSCSIRAID等。



    网络----以太网,光纤网,蜂窝网络,WIFIVLAN等。



    计算机体系结构,主要就是CPU指令集。x86,ARM等。



    USB协议。需要知道URB包。



    PCI协议,PCI-E协议。现代计算机的外设都是PCI协议和PCI-E协议的。显卡现在全是通过 PCI-E协议连接到计算机上的。相对来说减少了很多需要学习的知识。搞虚拟化就需要深入掌握PCI协议。



    图像处理--图像压缩,视频实时编码等。

    3D游戏



    关系数据库



    NoSQL数据库



    操作系统



    分布式操作系统



    编译原理



    机器学习--现在大数据要用哦!



            了解这些领域知识,也包括了解该领域现有的商用硬件、商用软件和开源软件。很多时候,你要完成的工作,已经有现成的工具了。你只要使用现成的工具就可以完成任务,不需要进行开发。有时候,只需要组合现有的工具,写一些脚本就可以完成任务。

           如,我一次要实现一个双向同步任务。找到了一个优秀的开源软件Unison,编写一下配置文件就圆满地完成了任务。不需要编写任何代码。

           还有一次,要做高可用,用Python调用了几个开源软件就轻松实现了。

           编写安装程序,定制操作系统,知道了操作系统的领域知识,写几行脚本就可以轻松搞定。

           不具备领域知识的人,就可能不得不进行大量无谓的开发,甚至开发很久之后才发现,这根本就是一条死路。


          另外,扎实的领域知识,可以大大提高编程调试、查错的能力。知道编译器和编程语言运行时工作原理,就能快速根据编译错误和警告信息修改代码。


          知道操作系统底层运行机制,就能快速找到运行时错误的问题根源。如,有一次我编写一个windows升级服务程序。它是一个windows服务,需要执行dos脚本,这个脚本会替换掉这个windows服务本身。发现有时脚本执行无效,查了一晚上,发现当windows服务安装后,第一次启动就执行脚本时就会有权限问题,log都正确,但实际执行这个脚本没有任何效果。但一旦windows服务程序启动一次之后就ok。这必然是windows操作系统底层安全机制的问题,因为我对Windows内核了解不多,因此花了很长时间才发现这个问题,并对造成这个问题的根源并不清楚。



    0领域知识菜鸟

          对领域知识没有多少认知,通过搜索引擎找到一些该领域的软件和硬件的介绍性文章,按照文章指示配置和使用软件。勉强能够使用现有软硬件。



    1领域知识行家

         了解领域内常用硬件,深入掌握领域内常用软件的配置和使用技巧。能够使用现有软硬件熟练搭建解决方案,能够解决实际工作中遇到的种种问题。





    2领域知识专家

           当你不仅仅掌握了该领域的软件和工具,知道怎么用,还知道其原理,“知其然,也知其所以然”,就是该领域的知识专家了。

    你知道网络协议的原理,你才能在网络出现问题时知道是哪里可能出现了问题。是mac冲突,ip冲突,还是网络环路?


    你知道存储的原理,你才能知道为什么这种存储方式不适合虚拟化,那种存储方式适合虚拟化,另一种方式适合资料备份。


    你知道PCI协议,你才能知道你怎样才能虚拟化一个硬件设备。


    你知道网卡硬件协议,你才能模拟出一个虚拟机能正常使用的虚拟网卡。


    你知道视频编码格式和原理,才能知道什么视频格式占用带宽最少,什么视频格式占用CPU最少。


    你了解IntelVT/Amd V指令集,才能知道虚拟化是怎样实现的。


    你明白工作流其实就是状态机,在遇到复杂工作流程时,你才能知道怎样设计满足要求的工作流引擎。





    3科学家

             你是领域知识专家,但你的知识都是来自于书本,来自于其他人的。

             如果你满足于当领域知识专家,你只能拾人牙慧,永远别想超越。别人的研究成果,未必愿意告诉你。当别人告诉你的时候,它可能已经发现了更新的理论,并且新一代产品可能马上就要发布了。

            科学家是探索未知,勇于创新的人,是推动人类社会进步的人。



           传说,思科的一位高管曾经半开玩笑地说过:如果思科停止了新技术的研发,华为就会找不着方向这是在嘲笑华为只是处在领域知识专家的水平,只能山寨无法超越。我不知道华为的实际情况,但希望现在的华为已经走到了领跑者的位置。



            欧文·雅各布斯发现了CDMA码分多址的原理,并发现它在通讯上大有可为,组建了高通公司。高通公司主要以专利授权费为生,它雇佣了大量科学家在通讯领域展开研究。有人说高通是专利流氓。这些人不明白知识的价值。在他们眼里,Windows的合理价格就应该是5元钱,一张光盘的价格。iPhone就应该是1000多元裸机的价格。高通是专利流氓,那你也流氓一个CDMALTE出来给我看看!



           X86芯片在设计上没有考虑虚拟化。因此会有所谓的虚拟化漏洞出现。就是说,一些CPU特权指令执行时,在虚拟机环境下不会抛出异常,因此就无法切换到Host。这样,X86芯片上就无法运行虚拟机。


           VmWare公司是由美国的几位科学家在1998年创建的。他们发现可以使用二进制翻译的技术,在X86计算机上运行虚拟机。


           Xen虚拟化软件也是几位科学家发明的。他们发现只要修改虚拟机操作系统和Host操作系统的内核,在需要执行虚拟化漏洞指令时直接调用Host的功能,就可以实现虚拟化,而且大大提高了虚拟机的运行性能。


            后来,Intel为自己的芯片添加了IntelVT指令集,Amd为自己的芯片添加了AmdV指令集,弥补了虚拟化漏洞。于是就有了KVM虚拟机软件,它直接用CPU硬件指令实现虚拟化。


           KVM在执行CPU指令时,是直接在物理CPU上运行的,因此效率极高。但是,虚拟机运行虚拟外设时,就必须用软件模拟,因此虚拟机的IO访问速度很慢。


           IBM科学家RustyRussell,借鉴了Xen的研发经验,创建了VirtIO技术。就是在虚拟机中编写一套PCI虚拟设备和驱动,这套虚拟PCI设备有一块虚拟设备内存。这个虚拟设备内存Host是可以访问的,虚拟机通过VirtIO驱动程序也可以访问。也就是一块内存在虚拟机和Host中共享,这就解决了虚拟机的IO性能问题。



    再讲一个搜索引擎的故事:

          很久以前,我要给一个程序添加搜索功能。刚开始使用sql查询实现,发现实在太慢了。后来找了开源的Lucene项目。它使用反向索引技术,通过在文件中创建反向索引,大大提高了搜索速度。


          Google的两位创始人发现了htmllink的秘密,他们发现可以通过html页面的link关系来为每一个html页面设置权重。也就是PageRank算法。于是,Google的自动搜索引擎击败了Yahoo人工分类的搜索引擎。


           OK,利用反向索引技术和PageRank,以及一个简单的html爬虫机器人,我们就可以创建一个搜索引擎了。但是,互联网很大,每天产生大量新网页,要为整个互联网建立反向索引是很困难的。


           若干年后Google又公开了三篇论文:Googlefs,Mapreduce,Bigtable。于是Lucene项目的开发者根据GoogleMapreduce论文开发了Hadoop项目。MapReduce就是使用大量计算机存储数据并计算,最后汇总结果。使用Hadoop+反向索引+PageRank,就可以创建搜索引擎了。Yahoo,Baidu等公司纷纷基于Hadoop开发了自己的搜索引擎。


            但是,其他公司的搜索引擎效果还是没法和Google相比。这一点我们程序员最清楚。像我,就总是翻墙出去,只为了Google一下。


            Google黑板报上发表了吴军博士的一些文章,其中介绍了很多机器学习方面的知识。从文中可以知道,Google其实使用机器学习来分析搜集到的页面。Google明显不会把这个公式公开出来。即使有一天Google真的公开了这个公式,那么可以想见Google肯定又研发出了更加犀利的秘籍,山寨货的搜索引擎效果还是比不上Google的。


           山寨是通向创新的必由之路。在成为领域的领头羊和领导者之前,必然要经过学习,模仿的阶段。但要成为行业的老大,成为Champion,必须勇于弯道超车,勇敢地走上创新之路,成为真正的科学家,真正的大牛!





    总结

             编程能力可分为两个维度:一个是编程技能水平,另一个是领域知识水平。

            有些程序员可能把精力都花在提升编程技能上了,领域知识知之甚少,这其实在日常工作中也是极其有害的。有些需求可能早已经有了现成、开源免费的解决方案,或者只需要组合几个现有软件就可以快速搞定,而他们却不得不自己花大量时间去开发。另外,缺少领域知识,在程序出现非预期状况时,很难快速定位到问题的根源,很难解决bug

    展开全文
  • 以太网的网络层次

    2021-04-17 15:47:32
    以太网的网络层次 以太网采用无源的介质,按广播方式传播信息。它规定了物理层和数据链路层协议,规定了物理层和数据链路层的接口以及数据链路层与更高层的接口。 物理层 物理层规定了以太网的基本物理属性,如...

    以太网的网络层次

    以太网采用无源的介质,按广播方式传播信息。它规定了物理层和数据链路层协议,规定了物理层和数据链路层的接口以及数据链路层与更高层的接口。

    物理层

    物理层规定了以太网的基本物理属性,如数据编码、时标、电频等。

    物理层位于OSI参考模型的最底层,它直接面向实际承担数据传输的物理媒体(即通信通道),物理层的传输单位为比特(bit),即一个二进制位(“0”或“1”)。实际的比特传输必须依赖于传输设备和物理媒体,但是,物理层不是指具体的物理设备,也不是指信号传输的物理媒体,而是指在物理媒体之上为上一层(数据链路层)提供一个传输原始比特流的物理连接。

    数据链路层

    数据链路层是OSI参考模型中的第二层,介于物理层和网络层之间。数据链路层在物理层提供的服务的基础上向网络层提供服务,其最基本的服务是将源设备网络层转发过来的数据可靠地传输到相邻节点的目的设备网络层。

    由于以太网的物理层和数据链路层是相关的,针对物理层的不同工作模式,需要提供特定的数据链路层来访问。这给设计和应用带来了一些不便。

    为此,一些组织和厂家提出把数据链路层再进行分层,分为媒体接入控制子层(MAC)和逻辑链路控制子层(LLC)。这样不同的物理层对应不同的MAC子层,LLC子层则可以完全独立。如图1所示。

    图 以太网链路层的分层结构:

    展开全文
  • 编程能力层次模型 .

    2015-04-10 08:51:26
     下面通过两个维度展开编程能力层次模型的讨论。  一个维度是编程技能层次,另一个维度是领域知识层次。 编程技能层次  编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本。 0段—...
  • 下面哪个不是TCP/IP协议中的层次 A、 网络层 B、 传输层 C、 应用层 D、 会话层 我的答案:D 2 【单选题】 TCP/IP协议中网络层的数据被称为 A、 Segment B、 Package C、 Frame D、 Message 我的答案:B 3 【单选题...
  • 网卡、网线:物理层 中继器:物理层 集线器:物理层,相当于多个中继器并在一起 网桥:链路层 交换机:链路层,相当于多个网桥并在...注意,交换机指传统的以太网交换机,即二层交换机,如今有三层、四层等交换机...
  • 新一代以太网通常是指速度超过10 Gb/s的以太网,为开展和推动新一代以太网更深入的研究,介绍了国内外的研究进展,利用结构化功能分层方法构建了40 GbE和100 GbE在不同传输模式下的层次结构模型和功能模型,并对各参量...
  • CISCO有自己的3层层次模型

    千次阅读 2010-10-26 08:20:00
    如果大家看过了CCNA之类的书就会知道:CISCO有自己的3层层次模型 1,接入层 2分配层 3,核心层 接入层有时也称桌面层,是控制用户和工作组对互联网络资源的访问的。大多数的用户所需要的资源在本地就可以得到,分配...
  • (掌握分层模型作用、数据帧结构、MAC、转发过程) 6.1 什么是协议: 为了使数据可以在网络上从源传递到目的地,网络上所有的设备需要“讲”相同的“语言”,好比两个人交谈,要使用相同的语言。 数
  • 返回总目录 下一篇 ...基于 TCP/IP 的参考模型,可以将协议分成 4 个层次,从上到下分别为应用层、传输层、网际层和网络访问层,如下图所示。分层以后,层中的协议只负责该层的数据处理。 TCP.
  • CISCO有自己的3层层次模型 1,接入层 2,汇聚层 3,核心层 区别:通常将网络中直接面向用户连接或访问网络的部分称为接入层,将位于接入层和核心层之间的部分称为分布层或汇聚层。 接入交换机:接入交换机一般...
  • 以太网和工业以太网

    2016-10-01 23:18:00
    OSI参考模型中的数据链路层定义了通过通信媒介互联的设备之间传输的规范,数据链路的传输方式有以太网、WLAN(无线局域网如Wifi/蓝牙/3G/4G/WiMAx/ZigBee等)、PPP(点对点)、ATM、FDDI、光纤通道、HDMI等,而...
  • OSI七层模型 模型把网络通信的工作分为7层。1至4层被认为是低层,这些层与数据移动密切相关。5至7层是高层,包含应用程序级的数据。每一层负责一项具体的工作,然后把数据传送到下一层。由低到高具体分为:物理层、...
  • 以太网

    2009-12-15 16:36:00
    1,在以太网中硬件必须在两次发送之间保持一个最小空闲时间,也就是说,没有一对正在通信的机器可以连续使用网络而不给其他机器接入的机会。2,关于HUB和交换机地球人都知道,HUB工作在物理层,交换机工作在链路层。...
  • 分层模型 OSI 七层和TCP/IP分层,及数据封装**终端之间的通信** 数据链路层控制数据帧在物理链路上传输。 数据包在以太网物理介质上传播之前必须封装头部和尾部信息。封装后的数据包称为称为数据帧,数据帧中封装...
  • 以太网交换机

    2020-07-06 05:47:24
    1、以太网交换机工作于OSI网络参考模型的第二层(即数据链路层),是一种基于MAC地址识别、完成以太网数据帧转发的网络设备。
  • OSI模型层次

    千次阅读 2017-08-14 21:26:10
    (单选题)中继器、以太网交换机、路由器分别工作在OSI模型的哪位层次上:(4分)   A.物理层、链路层、网络层 B.物理层、网络层、链路层 C.物理层、链路层、传输层 D.链路层、链路层、网络层  解析: 物理...
  • 以太网产生延迟的主要原因是冲突,其原因是它利用了CSMA/CD技术。在传统的共享网络中,由于以太网中所以的站点,采用相同的物理介质相连,这就意味着2台设备同时发出信号时,就会出现信号见的互相冲突。为了解决这个...
  • 什么是以太网

    千次阅读 2015-03-28 21:56:38
    首先需要明确一点:以太网是一种标准,而不是物理的网络。 以太网,英文名称是:Ethernet,由名称就可以知道,像局域网的英文名就是Local Area Network。...以太网应用于OSI七层模型的第六层—数据链路层。 数
  • 以太网帧结构详解

    万次阅读 多人点赞 2019-07-15 21:52:59
    以太网帧结构详解前言分层模型- OSI分层模型– TCP/IP数据封装终端之间的通信帧格式Ethernet_II 帧格式IEEE802.3 帧格式数据帧传输以太网的MAC地址数据帧的发送和接收单播广播组播发送与接收 前言 20世纪60年代以来...
  • OSI参考模型层次

    2020-10-14 21:28:14
    网桥,以太网交换机,网卡(一半物理层,一半数据链路层),调制解调器 网络层: 路由器,三层交换机 传输层: 四层交换机(常用作负载均衡),网桥:对高层协议(包括传输层及更高层次)进行转换的网间连接器。传输...
  • 3.以太网

    2020-03-10 18:30:03
    定义了OSI模型:开放式的系统互联;网络数据传输。 IEEF:互联网工程小组(主关路由协议); IEEE:电子与电气工程协会(局域网); 1980年2月成立了802委员会 网络中传输数据时需要定义并遵循一些标准,...
  • 车载以太网

    2021-01-24 22:43:06
    车载以太网协议架构 车载以太网协议是一组多个不同层次上的协议簇,但通常被认为是一个4层协议系统:应用层、传输层、网络层、数据链路层,每一层具有不同的功能。4层结构对应于 OSI 参考模型,并且提供了各种协议...
  • 车载以太网概述

    千次阅读 2019-11-09 15:44:37
    1.什么是车载以太网? 车载以太网是用于连接汽车内各种电气设备的一种物理网络。车载以太网的设计是为了满足车载环境中的一些特殊需求。例如:满足车载设备对于电气特性的要求(EMI/RF);满足车载设备对高带宽、低...
  • 如图是一个10BASE5以太网,每个主机都是用同一根同轴电缆来与其它 主机进行通信,因此,这里的同轴电缆又被称为共享介质,相应的网络 被称为共享介质网络,或简称为共享式网络。共享式网络中,不同的主 机同时发送...
  • 时间触发以太网TTE

    千次阅读 2019-05-23 22:58:08
    在激烈的竞争中时间触发以太网脱颖而出,其将时间触发技术的确定性、容错机制和实时性能同普通以太网的灵活性、动态性能以及“尽力而为”相结合,为同步的、高度可靠嵌入式计算与网络、容错设计提供支持

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,849
精华内容 5,539
关键字:

以太网层次模型