精华内容
下载资源
问答
  • 2021-06-06 11:06:24


    在这里插入图片描述


    组合思维

    Unix 操作系统诞生于 20 世纪 60 年代,经过几十年的发展,技术日臻成熟。在这个过程中,Unix 独特的设计哲学和美学也深深地吸引了一大批技术开发人员,他们在维护和使用 Unix 的同时,Unix 也影响了他们的思考方式和看待世界的角度。


    Unix 哲学是一套基于 Unix 操作系统顶级开发者们的经验所提出的软件开发的准则和理念

    也就是说,Unix 哲学并不是正统的计算机科学理论,它的形成更多是以经验为基础。你一定听说过模块化、解耦、高内聚低耦合这些设计原则,还有类似开源软件和开源社区文化,这些最早都是起源于 Unix 哲学。可以说 Unix 哲学是过去几十年里对软件行业影响意义最深远的编程文化。

    Unix 设计哲学,主张组合设计,而不是单体设计;主张使用集体智慧,而不是某个人的特殊智慧

    对编程的启示:

    • 启示一:保持简单清晰性,能提升代码质量

    代码之间的相互影响越多,软件越复杂。比如,A 依赖 B,B 依赖 C……一直这样循环下去,程序就会变得非常复杂,也就是我们编程中常说的,如果一个类文件写了上万行代码,那么代码逻辑将会非常难理解。

    软件复杂度一般有以下三个来源。

    • 代码库规模。

      这个就与开发工具、编程语言等有关了,不过需要注意,代码行数与复杂度并不呈正相关。比如,Java 语言编写的库通常会比 C++ 的库的代码行数更多(语言特性决定),但不能说 Java 类库就一定比 C++ 的类库更复杂。

    • 技术复杂度。

      这个指的是不同的编程语言、编译器、服务器架构、操作系统等能够被开发人员理解的难易程度。比如,Netty 库,对于很多 Java 程序员来说,理解起来就有一定的难度,这就是有一定的技术复杂度。

    • 实现复杂度。

      不同的编程人员,对于需求的理解不同,在编程时就会有截然不同的编写风格,比如,前端程序员和后端程序员网页分页的代码实现风格就会明显不同。


    该如何降低软件复杂度呢?

    首先,在代码库规模方面,可以通过减少硬编码来控制代码量

    比如,使用设计模式中的策略模式来替换大量的 if-else 语句,使用通用工具类来减少重复的方法调用。除此之外,还可以利用语言特性来减少代码量,比如,在 Java 8 中使用 lambda 表达式来精简语句。

    其次,对于技术复杂度来说,要想在整体上保持简单性,需要在设计时就做好技术选型

    换句话说,好的技术选型能够有效控制组件引入技术复杂度的风险。比如,在做系统设计时,引入像 Kafka 这样的消息中间件之前,你需要从系统吞吐量、响应时间要求、业务特性、维护成本等综合维度评估技术复杂度,如果你的系统并不需要复杂的消息中间件,那么就不要引入它,因为一旦引入后,就会面临指派人员学习与维护、出现故障后还要能及时修复等问题。

    最后,就降低实现复杂度而言,可以使用统一的代码规范

    比如,使用 Google 开源项目的编码规范,里面包含了命名规范、注释格式、代码格式等要求。这样做的好处在于,能快速统一不同开发人员的编程风格,避免在维护代码时耗费时间去适应不同的代码风格。

    所以,Unix 哲学中所说的保持简单性,并不单单是做到更少的代码量,更是在面对不同复杂度来源时也能始终保持简单清晰的指导原则


    • 启示二:借鉴组合理念,有效应对多变的需求

    对于任何一个开发团队来说,最怕遇见的问题莫过于:不停的需求变更导致不停的代码变更。

    即便你花费了大量的时间,在项目前期做了详细的需求分析和系统的分析设计,依然不能完全阻挡需求的变化,而一旦需求发生变更,那么就意味着开发团队需要加班加点地修改代码。

    事实上,Unix 在设计之初就已经遇见过这些问题,那它是怎么解决的呢?下面我们就来看一下 Unix 那些能够“任意组合”的例子。

    • 所有的命令都可以使用管道来交互

    这样,所有命令间的交互都只和 STD_IN、STD_OUT 设备相关。于是,就可以使用管道来任意地拼装不同的命令,以完成各式各样的功能。

    • 可以任意地替换程序

    比如,我喜欢 zsh,你喜欢 bash,我们可以各自替换;你喜欢 awk,我不喜欢 awk,也可以替换为 gawk。快速切换到熟悉的程序,每个程序就像一个零件一样,任意插拔。

    • 自定义环境变量

    比如,Java 编译环境有很多版本,你可能用到的有版本 8、11 和 14,通过自定义 JAVA_HOME 环境变量,你就可以快速启用不同的编译环境。

    这充分说明了 Unix 哲学的组合思维把软件设计成独立组件并能随意地组合,才能真正应对更多变化的需求。

    然而,在实际工作中,你很多时候可能都只是在做“定制功能驱动”式的程序设计。比如,用户需要一个“上传文件的红色按钮”,你就实现了一个叫“红色上传按钮功能”的组件,过几天变为需要一个“上传文件的绿色按钮”时,你再修改代码满足要求……这不是组合设计,而是直接映射设计,看似用户是需要“上传”这个功能,但实际上用户隐藏了对“不同颜色”的需求。

    很多时候看上去我们是一直在设计不同的程序,实际上对于真正多变的需求,我们并没有做到组合设计,只是通过不断地修改代码来掩饰烂设计罢了。

    要想做到组合设计,Unix 哲学其实给我们提供了两个解决思路。

    第一个是解耦

    这是 Unix 哲学最核心的原则。代码与代码之间的依赖关系越多,程序就越复杂,只有将大程序拆分成小程序,才能让人容易理解它们彼此之间的关系。也就是我们常说的在设计时应尽量分离接口与实现,程序间应该耦合在某个规范与标准上,而不是耦合在具体代码实现逻辑上

    第二个是模块化

    你可能已经非常熟悉这个词语了,不过模块化还有更深层的含义——可替换的一致性。什么叫可替换的一致性?比如,你想使用 Java RPC 协议,可以选择 Dubbo、gRPC 等框架,RPC 协议的本质是一样的,就是远程过程调用,但是实现的组件框架却可以不同,对于使用者来说,只要是支持 Java RPC 协议的框架就行,可随意替换,这是可替换。而不同的框架需要实现同一个功能(远程过程调用)来保持功能的一致性(Dubbo 和 gRPC 的功能是一致的),这是一致性。

    实际上,这两个解决思路就是现在我们常说的高内聚、低耦合原则:模块内部尽量聚合以保持功能的一致性,模块外部尽量通过标准去耦合。

    换句话说,就是提供机制而不是策略,就像上传文件那个例子里,分析时应该找出用户隐含的颜色变化的需求,并抽象出一个可以自定义颜色的功能模块,解耦上传文件模块,最后将颜色变化模块组合到上传文件模块来对外提供使用。这样当用户提出修改颜色时(修改策略),只需要修改自定义颜色模块就行了,而不是连同上传文件的机制也一起修改。


    • 启示三:重拾数据思维,重构优化程序设计

    再高大上的架构设计,如果系统对数据的组织是混乱的,那么可以轻松预见随着系统的演进,系统必然会变得越来越臃肿和不可控。

    Unix 哲学在出现之初便提出了“数据驱动编程”这样一个重要的编程理念。也就是说,在 Unix 的理念中,编程中重要的是数据结构,而不是算法。

    当数据结构发生变化时,通常需要对应用程序代码进行修改,比如,添加新数据库字段、修改程序读写字段等。但在大多数应用程序中,代码变更并不是立即完成的。原因有如下:

    • 对于服务端应用程序而言,可能需要执行增量升级,将新版本部署到灰度环境,检查新版本是否正常运行,然后再完成所有的节点部署;

    • 对于客户端应用程序来说,升不升级就要看用户的心情了,有些用户可能相当长一段时间里都不会去升级软件。

    这就意味着新旧版本的代码以及新旧数据格式可能会在系统中同时共存。这时,处理好数据的兼容性就变得非常重要了。如果不具备数据思维,很可能会假设数据格式的变更不会影响代码变更。

    Unix 哲学提出的“数据驱动编程”会把代码和代码作用的数据结构分开,这样在改变程序的逻辑时,就只要编辑数据结构,而不需要修改代码了


    分层思维

    软件程序通常有两个层面的需求:

    • 功能性需求,简单来说,就是一个程序能为用户做些什么,比如,文件上传、查询数据等;

    • 非功能性需求,这个是指除功能性需求以外的其他必要需求,比如,性能、安全性、容错与恢复、本地化、国际化等。

    事实上,非功能性需求所构建起来的正是我们所熟知的软件架构。什么是软件架构?简单来说,就是软件的基本结构,包括三要素:代码、代码之间的关系和两者各自的属性。

    如果把软件比作一座高楼,那么软件架构就是那个钢筋混凝土的框架,代码就是那个框架里的砖石,正是因为有了那个框架,才能让每一个代码都能很好地运行起来。

    其中,最为经典的软件架构就是分层架构, 分层架构越是流行,我们的设计越容易僵化。这背后到底有哪些值得我们深思的地方呢?

    从架构角度来聊聊为什么代码要做分层、主要用于解决什么问题,以及存在优势和劣势有哪些。

    工程思维

    对象思维

    迭代思维

    更多相关内容
  • ERP系统集成实例 - 适应新常态

    千次阅读 2022-01-28 16:26:22
    眼下,持续的新冠疫情(COVID-19)对全球供应链产生了重大的影响,迫使制造商重新考虑其供应商和客户的管理方式,是否需要集成ERP系统来实现? ERP可以将各种不同的业务功能和数据源联系在一起,形成一个数据共享...

    眼下,持续的新冠疫情(COVID-19)对全球供应链产生了重大的影响,迫使制造商重新考虑其供应商和客户的管理方式,是否需要集成ERP系统来实现。正如德勤(Deloitte)所指出的那样,那些在原材料和成品方面依赖中国的公司受到的冲击最为严重,尤其是那些在武汉有直接利益的公司- 而《财富》世界500强公司中有200家在该地区有业务。因此,即使全球经济在未来几个月恢复至某种形式的正常水平,也无法保证这些供应链中断将完全消失。

    为不确定的未来做准备

    几十年来,制造企业不断优化IT系统和后端流程,以达到降低成本、有效管理库存和最大化资产利用。尽管这些努力帮助部分企业缓解了较小程度的供应中断,但绝大多数企业从未面临过像新冠疫情(COVID-19)这样严重的威胁。

    在供应链限制、全公司封锁和远程工作指令的影响下,制造企业很难赶上他们的生产进度。除此之外,据世界经济论坛(World Economic Forum)的报道称,由于许多供应商暂时限制了他们的业务以帮助防止病毒的传播,使得制造商面临着“采购渠道短缺”的困境。一些对全球经济衰退还没做好准备的企业,或许在此次疫情中已敏锐地意识到了自己供应链关系的脆弱,但许多企业仍未找到长期解决方案所需的可见性和商务智能。

    幸运的是,大量基于云的业务应用为制造商提供了更大的端到端可见性和一系列自动化的工具,可以支持更广泛的数字化转型,其中之一就是企业资源管理软件(ERP)。它可以将各种不同的业务功能和数据源联系在一起,形成一个数据共享平台,制造商利用该平台可以精确地管理从原材料、采购到人力资源乃至更多领域的日常运营。当然,对于有多种数据格式、孤岛式业务应用和复杂供应链的公司而言,ERP系统的集成可能会面临挑战。

    ERP系统集成的好处

    现代ERP软件具有多种不同的功能,可以灵活定制以满足企业的确切需求,从而帮助企业实现业务流程的自动化并促进高效的数据转换。对于制造企业来说,集成的ERP解决方案代表了一种宝贵的商务智能资源,可以涉及其供应链的各个阶段。在不确定时期,制造商需要依赖这种准确的、实时的数据来帮助他们做出决策并优化后端流程。其中包括自动化数据输入、与供应商合作、修改生产计划以及汇总各个来源(会计、库存、销售、物流等)的关键业务信息等等。ERP系统集成的主要好处包括:

    • 增加流动性:根据Gartner的一项研究报告显示,74%的公司计划在新冠疫情(COVID-19)之后,将至少一部分的劳动力转移到长期在家工作的岗位上。因此,为员工提供一种能远程访问关键数据和业务应用程序的简单方式,比以往任何时候都更加重要。基于云的ERP软件可以在任何有互联网连接的设备上使用,允许制造商在不需要亲自访问生产现场的情况下快速响应中断。
    • 简化协作:几乎所有的ERP解决方案都能提供先进的数据集成工具,帮助制造商集中关键业务信息。这不仅可以大大促进部门间的合作,还能确保业务领导者拥有其所需的数据,以主动与供应商、商业伙伴和客户进行谈判。
    • 提高生产力:自动化已成为制造业的主导趋势,但许多公司仍在努力解决后端流程中的冗余问题。ERP系统集成能为制造商提供所需的可视性和控制力,以优化其日常运营,同时最大程度地减少生产延迟。实际上,据IT咨询公司Panorama的一项研究调查发现,95%的公司在部署ERP系统之后确实“改进了他们的流程”
    • 降低IT成本:ERP软件的最大优势之一,就是它能使制造商在一个单一的、集中式的管理平台下整合其所有的业务应用。通过消除不同数字解决方案之间的孤岛,企业可以优化其IT支出,并专注于真正重要的事情 - 发展业务。虽然ERP产品提供的功能多样,但绝大多数都配备了专门的工具用于客户资源管理(CRM)、会计、人力资源、供应链管理等。

    由于每个制造企业都有自己的运营需求和预算限制,所以在进行长期投资之前,仔细评估ERP供应商是十分重要的。企业应优先考虑可定制的ERP解决方案,将“可扩展性”列为首要,以轻松适应不断变化的业务环境。更重要的是,缺少集成的ERP解决方案可能会导致各种程度的效率低下 – 根据全球营销公司Aberdeen的一项研究调查显示,冗余数据(35%)、无序的业务系统(33%)以及无法实时跟踪流程(28%)都是选择退出ERP系统集成后常见的后果。

    考虑到新冠疫情(COVID-19)的不确定性,现在也许是将ERP软件集成到现有制造工作流程中的最佳时机。如果没有合适的解决方案,企业可能难以快速有效地应对未来的供应链中断。

     


    您的ERP系统不够灵活? 试试abas ERP!


    WECHAT US:

    abas China

    Total ERP Solution for Mid-Market Businesses

    Shanghai丨Beijing丨Shenzhen丨HongKong

    400-900-3906丨info@abas.cn

    www.abas.cn

    展开全文
  • 【STM32】系统时钟RCC详解(超详细,超全面)

    万次阅读 多人点赞 2019-08-08 15:42:35
    时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。 为什么 STM32 ...

    1什么是时钟

    时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。

     

    为什么 STM32 要有多个时钟源呢?

    STM32本身十分复杂,外设非常多  但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费   并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的MCU都是采用多时钟源的方法来解决这些问题。所以便有了STM32的时钟系统和时钟树

     

    总括:

    • STM32时钟系统主要的目的就是给相对独立的外设模块提供时钟,也是为了降低整个芯片的耗能
    • 系统时钟,是处理器运行时间基准(每一条机器指令一个时钟周期)
    • 时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。
    • 一个单片机内提供多个不同的系统时钟,可以适应更多的应用场合。
    • 不同的功能模块会有不同的时钟上限,因此提供不同的时钟,也能在一个单片机内放置更多的功能模块。
      对不同模块的时钟增加开启和关闭功能,可以降低单片机的功耗
    • STM32为了低功耗,他将所有的外设时钟都设置为disable(不使能),用到什么外设,只要打开对应外设的时钟就可以, 其他的没用到的可以还是disable(不使能),这样耗能就会减少。  这就是为什么不管你配置什么功能都需要先打开对应的时钟的原因

     

    STM32的时钟系统框图

     

    乍一看很吓人,但其实很好理解,我们看系统时钟SYSCLK 的左边  系统时钟有很多种选择,而左边的部分就是设置系统时钟使用那个时钟源,   

    系统时钟SYSCLK 的右边,则是系统时钟通过AHB预分频器,给相对应的外设设置相对应的时钟频率

     

    从左到右可以简单理解为  各个时钟源--->系统时钟来源的设置--->各个外设时钟的设置

    时钟系统

    1各个时钟源    (左边的部分)

    STM32 有4个独立时钟源:HSI、HSE、LSI、LSE。
    ①、HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。
    ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz
    ③、LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟。  
    ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。

    其中LSI是作为IWDGCLK(独立看门狗)时钟源和RTC时钟源 而独立使用 

    而HSI高速内部时钟 HSE高速外部时钟 PLL锁相环时钟  这三个经过分频或者倍频 作为系统时钟来使用

     

    PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。  通过倍频之后作为系统时钟的时钟源

     

    举个例子:Keil编写程序是默认的时钟为72Mhz,其实是这么来的:外部晶振(HSE)提供的8MHz(与电路板上的晶振的相关)通过PLLXTPRE分频器后,进入PLLSRC选择开关,进而通过PLLMUL锁相环进行倍频(x9)后,为系统提供72MHz的系统时钟(SYSCLK)。之后是AHB预分频器对时钟信号进行分频,然后为低速外设提供时钟。

    或者内部RC振荡器(HSI) 为8MHz  /2 为4MHz 进入PLLSRC选择开关,通过PLLMUL锁相环进行倍频(x18)后 为72MHz

     

    PS:  网上有很多人说是5个时钟源,这种说法有点问题,学习之后就会发现PLL并不是自己产生的时钟源,而是通过其他三个时钟源倍频得到的时钟

    2系统时钟SYSCLK

    系统时钟SYSCLK可来源于三个时钟源:
    ①、HSI振荡器时钟
    ②、HSE振荡器时钟
    ③、PLL时钟
    最大为72Mhz

     

    3USB时钟

    STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取(唯一的),,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz

    4把时钟信号输出到外部

    STM32可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。可以把时钟信号输出供外部使用

    5系统时钟通过AHB分频器给外设提供时钟(右边的部分)  重点

     

    从左到右可以简单理解为  系统时钟--->AHB分频器--->各个外设分频倍频器 --->   外设时钟的设置

     

    右边部分为:系统时钟SYSCLK通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用: 

     ①内核总线:送给AHB总线、内核、内存和DMA使用的HCLK时钟。 

     ②Tick定时器:通过8分频后送给Cortex的系统定时器时钟。 

     ③I2S总线:直接送给Cortex的空闲运行时钟FCLK。 

     ④APB1外设:送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给通用定时器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2-7使用。 

     ⑤APB2外设:送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给高级定时器。该倍频器可选择1或者2倍频,时钟输出供定时器1和定时器8使用。

     

    另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、8分频。 

    需要注意的是,如果 APB 预分频器分频系数是 1,则定时器时钟频率 (TIMxCLK) 为 PCLKx。否则,定      时器时钟频率将为 APB 域的频率的两倍:TIMxCLK = 2xPCLKx。 

    APB1和APB2的对应外设

    F1系列

    APB1上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、USART2、USART3、UART4、UART5、SPI2、SP3等;

    而APB2上面连接的是高速外设,包括UART1、SPI1、Timer1、ADC1、ADC2、ADC3、所有的普通I/O口(PA-PE)、第二功能I/O(AFIO)口等。


    F4系列

    这个和F1系列类似,我们就举几个特殊的

     APB2总线:高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11   UTART1,USART6

     APB1总线:通用定时器timer2~timer5,通用定时器timer12~timer14以及基本定时器timer6,timer7  UTART2~UTART5

    F4系列的系统时钟频率最高能到168M

     

    具体  可以在 stm32f10x_rcc.h  和stm32f40x_rcc.h   中查看

    或者通过 STM32参考手册搜索“系统架构”或者“系统结构”  查看外设挂在哪个时钟下

     

    RCC相关寄存器:

    这里我们以F1系列为例

    RCC 寄存器结构,RCC_TypeDeff,在文件“stm32f10x.h”中定义如下:
    
    1059行->1081行。:  
    typedef struct  
    {  
    vu32 CR;                  //HSI,HSE,CSS,PLL等的使能  
    vu32 CFGR;              //PLL等的时钟源选择以及分频系数设定 
    vu32 CIR;                // 清除/使能 时钟就绪中断 
    vu32 APB2RSTR;      //APB2线上外设复位寄存器 
    vu32 APB1RSTR;      //APB1线上外设复位寄存器 
    vu32 AHBENR;         //DMA,SDIO等时钟使能 
    vu32 APB2ENR;       //APB2线上外设时钟使能 
    vu32 APB1ENR;      //APB1线上外设时钟使能 
    vu32 BDCR;           //备份域控制寄存器 
    vu32 CSR;             
    } RCC_TypeDef; 
    

    可以对上上面的时钟框图和RCC寄存器来学习,对STM32的时钟系统有个大概的了解   其实也就是我们上面介绍的流程,理解了自然也就能写出来

    RCC初始化:

    这里我们使用HSE(外部时钟),正常使用的时候也都是使用外部时钟

    使用HSE时钟,程序设置时钟参数流程:
    1、将RCC寄存器重新设置为默认值   RCC_DeInit;
    2、打开外部高速时钟晶振HSE       RCC_HSEConfig(RCC_HSE_ON);
    3、等待外部高速时钟晶振工作      HSEStartUpStatus = RCC_WaitForHSEStartUp();
    4、设置AHB时钟         RCC_HCLKConfig;
    5、设置高速AHB时钟     RCC_PCLK2Config;
    6、设置低速速AHB时钟   RCC_PCLK1Config;
    7、设置PLL              RCC_PLLConfig;
    8、打开PLL              RCC_PLLCmd(ENABLE);
    9、等待PLL工作          while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    10、设置系统时钟        RCC_SYSCLKConfig;
    11、判断是否PLL是系统时钟     while(RCC_GetSYSCLKSource() != 0x08)
    12、打开要使用的外设时钟      RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()

    代码实现:

    对RCC的配置函数(使用外部8MHz晶振)  

    系统时钟72MHz,APH 72MHz,APB2 72MHz,APB1 32MHz,USB 48MHz TIMCLK=72M

    void RCC_Configuration(void)
    {
    	//----------使用外部RC晶振-----------
    	RCC_DeInit();			//初始化为缺省值
    	RCC_HSEConfig(RCC_HSE_ON);	//使能外部的高速时钟 
    	while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);	//等待外部高速时钟使能就绪
    	
    	FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer
    	FLASH_SetLatency(FLASH_Latency_2);		//Flash 2 wait state
    	
    	RCC_HCLKConfig(RCC_SYSCLK_Div1);		//HCLK = SYSCLK
    	RCC_PCLK2Config(RCC_HCLK_Div1);			//PCLK2 =  HCLK
    	RCC_PCLK1Config(RCC_HCLK_Div2);			//PCLK1 = HCLK/2
    	RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);	//PLLCLK = 8MHZ * 9 =72MHZ
    	RCC_PLLCmd(ENABLE);			//Enable PLLCLK
     
    	while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);	//Wait till PLLCLK is ready
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	//Select PLL as system clock
    	while(RCC_GetSYSCLKSource()!=0x08);		//Wait till PLL is used as system clock source
    	
    	//---------打开相应外设时钟--------------------
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//使能APB2外设的GPIOA的时钟		 
    }
    

    也就是我们时钟树框图从左到右的配置,

    时钟监视系统(CSS)

    STM32还提供了一个时钟监视系统(CSS),用于监视高速外部时钟(HSE)的工作状态。倘若HSE失效,会自动切换(高速内部时钟)HSI作为系统时钟的输入,保证系统的正常运行。

     

     

    展开全文
  • 为了更真实地仿真现实的网络世界和提高模型的适应性,研究一类具有双重时滞和非时滞耦合的复杂网络同步问题。不同于大多数研究中限定耦合矩阵满足耗散耦合条件,对耦合矩阵未添加任何限制。基于李雅普诺夫稳定性定理...
  • 降低软件复杂性的一般原则和方法

    千次阅读 2019-09-24 10:37:31
    其实,回答好第二个问题很重要,大型软件的设计已经复杂到没人能够一次就想到最佳方案,一个仅仅“可行”的方案,可能会给系统增加额外的复杂性。对聪明人来说,接受这点更困难,因为他们习惯于“一次搞定问题”。...

    一、前言

    斯坦福教授、Tcl语言发明者John Ousterhout 的著作《A Philosophy of Software Design》[1],自出版以来,好评如潮。按照IT图书出版的惯例,如果冠名为“实践”,书中内容关注的是某项技术的细节和技巧;冠名为“艺术”,内容可能是记录一件优秀作品的设计过程和经验;而冠名为“哲学",则是一些通用的原则和方法论,这些原则方法论串起来,能够形成一个体系。正如”知行合一”、“世界是由原子构成的”、“我思故我在”,这些耳熟能详的句子能够一定程度上代表背后的人物和思想。用一句话概括《A Philosophy of Software Design》,软件设计的核心在于降低复杂性。

    本篇文章是围绕着“降低复杂性”这个主题展开的,很多重要的结论来源于John Ousterhout,笔者觉得很有共鸣,就做了一些相关话题的延伸、补充了一些实例。虽说是"一般原则“,也不意味着是绝对的真理,整理出来,只是为了引发大家对软件设计的思考。

    二、如何定义复杂性

    关于复杂性,尚无统一的定义,从不同的角度可以给出不同的答案。可以用数量来度量,比如芯片集成的电子器件越多越复杂(不一定对);按层次性[2]度量,复杂度在于层次的递归性和不可分解性。在信息论中,使用熵来度量信息的不确定性。

    John Ousterhout选择从认知的负担和开发工作量的角度来定义软件的复杂性,并且给出了一个复杂度量公式:

    子模块的复杂度cp乘以该模块对应的开发时间权重值tp,累加后得到系统的整体复杂度C。系统整体的复杂度并不简单等于所有子模块复杂度的累加,还要考虑该模块的开发维护所花费的时间在整体中的占比(对应权重值tp)。也就是说,即使某个模块非常复杂,如果很少使用或修改,也不会对系统的整体复杂度造成大的影响。

    子模块的复杂度cp是一个经验值,它关注几个现象:

    • 修改扩散,修改时有连锁反应。
    • 认知负担,开发人员需要多长时间来理解功能模块。
    • 不可知(Unknown Unknowns),开发人员在接到任务时,不知道从哪里入手。

    造成复杂的原因一般是代码依赖和晦涩(Obscurity)。其中,依赖是指某部分代码不能被独立地修改和理解,必定会牵涉到其他代码。代码晦涩,是指从代码中难以找到重要信息。

    三、解决复杂性的一般原则

    首先,互联网行业的软件系统,很难一开始就做出完美的设计,通过一个个功能模块衍生迭代,系统才会逐步成型;对于现存的系统,也很难通过一个大动作,一劳永逸地解决所有问题。系统设计是需要持续投入的工作,通过细节的积累,最终得到一个完善的系统。因此,好的设计是日拱一卒的结果,在日常工作中要重视设计和细节的改进。

    其次,专业化分工和代码复用促成了软件生产率的提升。比如硬件工程师、软件工程师(底层、应用、不同编程语言)可以在无需了解对方技术背景的情况下进行合作开发;同一领域服务可以支撑不同的上层应用逻辑等等。其背后的思想,无非是通过将系统分成若干个水平层、明确每一层的角色和分工,来降低单个层次的复杂性。同时,每个层次只要给相邻层提供一致的接口,可以用不同的方法实现,这就为软件重用提供了支持。分层是解决复杂性问题的重要原则。

    第三,与分层类似,分模块是从垂直方向来分解系统。分模块最常见的应用场景,是如今广泛流行的微服务。分模块降低了单模块的复杂性,但是也会引入新的复杂性,例如模块与模块的交互,后面的章节会讨论这个问题。这里,我们将第三个原则确定为分模块。

    最后,代码能够描述程序的工作流程和结果,却很难描述开发人员的思路,而注释和文档可以。此外,通过注释和文档,开发人员在不阅读实现代码的情况下,就可以理解程序的功能,注释间接促成了代码抽象。好的注释能够帮助解决软件复杂性问题,尤其是认知负担和不可知问题(Unknown Unknowns)。

    四、解决复杂性之日拱一卒

    4.1 拒绝战术编程

    战术编程致力于完成任务,新增加特性或者修改Bug时,能解决问题就好。这种工作方式,会逐渐增加系统的复杂性。如果系统复杂到难以维护时,再去重构会花费大量的时间,很可能会影响新功能的迭代。

    战略编程,是指重视设计并愿意投入时间,短时间内可能会降低工作效率,但是长期看,会增加系统的可维护性和迭代效率。

    设计系统时,很难在开始阶段就面面俱到。好的设计应该体现在一个个小的模块上,修改bug时,也应该抱着设计新系统的心态,完工后让人感觉不到“修补”的痕迹。经过累积,最终形成一个完善的系统。从长期看,对于中大型的系统,将日常开发时间的10-15%用于设计是值得的。有一种观点认为,创业公司需要追求业务迭代速度和节省成本,可以容忍糟糕的设计,这是用错误的方法去追求正确的目标。降低开发成本最有效的方式是雇佣优秀的工程师,而不是在设计上做妥协。

    4.2 设计两次

    为一个类、模块或者系统的设计提供两套或更多方案,有利于我们找到最佳设计。以我们日常的技术方案设计为例,技术方案本质上需要回答两个问题,其一,为什么该方案可行? 其二,在已有资源限制下,为什么该方案是最优的?为了回答第一个问题,我们需要在技术方案里补充架构图、接口设计和时间人力估算。而要回答第二个问题,需要我们在关键点或争议处提供二到三种方案,并给出建议方案,这样才有说服力。通常情况下,我们会花费很多的时间准备第一个问题,而忽略第二个问题。其实,回答好第二个问题很重要,大型软件的设计已经复杂到没人能够一次就想到最佳方案,一个仅仅“可行”的方案,可能会给系统增加额外的复杂性。对聪明人来说,接受这点更困难,因为他们习惯于“一次搞定问题”。但是聪明人迟早也会碰到自己的瓶颈,在低水平问题上徘徊,不如花费更多时间思考,去解决真正有挑战性的问题。

    五、解决复杂性之分层

    5.1 层次和抽象

    软件系统由不同的层次组成,层次之间通过接口来交互。在严格分层的系统里,内部的层只对相邻的层次可见,这样就可以将一个复杂问题分解成增量步骤序列。由于每一层最多影响两层,也给维护带来了很大的便利。分层系统最有名的实例是TCP/IP网络模型。

    在分层系统里,每一层应该具有不同的抽象。TCP/IP模型中,应用层的抽象是用户接口和交互;传输层的抽象是端口和应用之间的数据传输;网络层的抽象是基于IP的寻址和数据传输;链路层的抽象是适配和虚拟硬件设备。如果不同的层具有相同的抽象,可能存在层次边界不清晰的问题。

    5.2 复杂性下沉

    不应该让用户直面系统的复杂性,即便有额外的工作量,开发人员也应当尽量让用户使用更简单。如果一定要在某个层次处理复杂性,这个层次越低越好。举个例子,Thrift接口调用时,数据传输失败需要引入自动重试机制,重试的策略显然在Thrift内部封装更合适,开放给用户(下游开发人员)会增加额外的使用负担。与之类似的是系统里随处可见的配置参数(通常写在XML文件里),在编程中应当尽量避免这种情况,用户(下游开发人员)一般很难决定哪个参数是最优的,如果一定要开放参数配置,最好给定一个默认值。

    复杂性下沉,并不是说把所有功能下移到一个层次,过犹不及。如果复杂性跟下层的功能相关,或者下移后,能大大下降其他层次或整体的复杂性,则下移。

    5.3 异常处理

    异常和错误处理是造成软件复杂的罪魁祸首之一。有些开发人员错误的认为处理和上报的错误越多越好,这会导致过度防御性的编程。如果开发人员捕获了异常并不知道如何处理,直接往上层扔,这就违背了封装原则。

    降低复杂度的一个原则就是尽可能减少需要处理异常的可能性。而最佳实践就是确保错误终结,例如删除一个并不存在的文件,与其上报文件不存在的异常,不如什么都不做。确保文件不存在就好了,上层逻辑不但不会被影响,还会因为不需要处理额外的异常而变得简单。

    六、解决复杂性之分模块

    分模块是解决复杂性的重要方法。理想情况下,模块之间应该是相互隔离的,开发人员面对具体的任务,只需要接触和了解整个系统的一小部分,而无需了解或改动其他模块。

    6.1 深模块和浅模块

    深模块(Deep Module)指的是拥有强大功能和简单接口的模块。深模块是抽象的最佳实践,通过排除模块内部不重要的信息,让用户更容易理解和使用。

    Unix操作系统文件I/O是典型的深模块,以Open函数为例,接口接受文件名为参数,返回文件描述符。但是这个接口的背后,是几百行的实现代码,用来处理文件存储、权限控制、并发控制、存储介质等等,这些对用户是不可见的。

    int open(const char* path, int flags, mode_t permissions);
    
    

    与深模块相对的是浅模块(Shallow Module),功能简单,接口复杂。通常情况下,浅模块无助于解决复杂性。因为他们提供的收益(功能)被学习和使用成本抵消了。以Java I/O为例,从I/O中读取对象时,需要同时创建三个对象FileInputStream、BufferedInputStream、ObjectInputStream,其中前两个创建后不会被直接使用,这就给开发人员造成了额外的负担。默认情况下,开发人员无需感知到BufferedInputStream,缓冲功能有助于改善文件I/O性能,是个很有用的特性,可以合并到文件I/O对象里。假如我们想放弃缓冲功能,文件I/O也可以设计成提供对应的定制选项。

    
    FileInputStream fileStream = new FileInputStream(fileName);
    BufferedInputStream bufferedStream = new BufferedInputStream(fileStream);
    ObjectInputStream objectStream = new ObjectInputStream(bufferedStream);
    
    

    关于浅模块有一些争议,大多数情况是因为浅模块是不得不接受的既定事实,而不见得是因为合理性。当然也有例外,比如领域驱动设计里的防腐层,系统在与外部系统对接时,会单独建立一个服务或模块去适配,用来保证原有系统技术栈的统一和稳定性。

    6.2 通用和专用

    设计新模块时,应该设计成通用模块还是专用模块?一种观点认为通用模块满足多种场景,在未来遇到预期外的需求时,可以节省时间。另外一种观点则认为,未来的需求很难预测,没必要引入用不到的特性,专用模块可以快速满足当前的需求,等有后续需求时再重构成通用的模块也不迟。

    以上两种思路都有道理,实际操作的时候可以采用两种方式各自的优点,即在功能实现上满足当前的需求,便于快速实现;接口设计通用化,为未来留下余量。举个例子。

    
    void backspace(Cursor cursor);
    void delete(Cursor cursor);
    void deleteSelection(Selection selection);
    
    //以上三个函数可以合并为一个更通用的函数
    void delete(Position start, Position end);
    
    

    设计通用性接口需要权衡,既要满足当前的需求,同时在通用性方面不要过度设计。一些可供参考的标准:

    • 满足当前需求最简单的接口是什么?在不减少功能的前提下,减少方法的数量,意味着接口的通用性提升了。
    • 接口使用的场景有多少?如果接口只有一个特定的场景,可以将多个这样的接口合并成通用接口。
    • 满足当前需求情况下,接口的易用性?如果接口很难使用,意味着我们可能过度设计了,需要拆分。

    6.3 信息隐藏

    信息隐藏是指,程序的设计思路以及内部逻辑应当包含在模块内部,对其他模块不可见。如果一个模块隐藏了很多信息,说明这个模块在提供很多功能的同时又简化了接口,符合前面提到的深模块理念。软件设计领域有个技巧,定义一个"大"类有助于实现信息隐藏。这里的“大”类指的是,如果要实现某功能,将该功能相关的信息都封装进一个类里面。

    信息隐藏在降低复杂性方面主要有两个作用:一是简化模块接口,将模块功能以更简单、更抽象的方式表现出来,降低开发人员的认知负担;二是减少模块间的依赖,使得系统迭代更轻量。举个例子,如何从B+树中存取信息是一些数据库索引的核心功能,但是数据库开发人员将这些信息隐藏了起来,同时提供简单的对外交互接口,也就是SQL脚本,使得产品和运营同学也能很快地上手。并且,因为有足够的抽象,数据库可以在保持外部兼容的情况下,将索引切换到散列或其他数据结构。

    与信息隐藏相对的是信息暴露,表现为:设计决策体现在多个模块,造成不同模块间的依赖。举个例子,两个类能处理同类型的文件。这种情况下,可以合并这两个类,或者提炼出一个新类(参考《重构》[3]一书)。工程师应当尽量减少外部模块需要的信息量。

    6.4 拆分和合并

    两个功能,应该放在一起还是分开?“不管黑猫白猫”,能降低复杂性就好。这里有一些可以借鉴的设计思路:

    • 共享信息的模块应当合并,比如两个模块都依赖某个配置项。
    • 可以简化接口时合并,这样可以避免客户同时调用多个模块来完成某个功能。
    • 可以消除重复时合并,比如抽离重复的代码到一个单独的方法中。
    • 通用代码和专用代码分离,如果模块的部分功能可以通用,建议和专用部分分离。举个例子,在实际的系统设计中,我们会将专用模块放在上层,通用模块放在下层以供复用。

    七、解决复杂性之注释

    注释可以记录开发人员的设计思路和程序功能,降低开发人员的认知负担和解决不可知(Unkown Unkowns)问题,让代码更容易维护。通常情况下,在程序的整个生命周期里,编码只占了少部分,大量时间花在了后续的维护上。有经验的工程师懂得这个道理,通常也会产出更高质量的注释和文档。

    注释也可以作为系统设计的工具,如果只需要简单的注释就可以描述模块的设计思路和功能,说明这个模块的设计是良好的。另一方面,如果模块很难注释,说明模块没有好的抽象。

    7.1 注释的误区

    关于注释,很多开发者存在一些认识上的误区,也是造成大家不愿意写注释的原因。比如“好代码是自注释的"、"没有时间“、“现有的注释都没有用,为什么还要浪费时间”等等。这些观点是站不住脚的。“好代码是自注释的”只在某些场景下是合理的,比如为变量和方法选择合适的名称,可以不用单独注释。但是更多的情况,代码很难体现开发人员的设计思路。此外,如果用户只能通过读代码来理解模块的使用,说明代码里没有抽象。好的注释可以极大地提升系统的可维护性,获取长期的效率,不存在“没有时间”一说。注释也是一种可以习得的技能,一旦习得,就可以在后续的工作中应用,这就解决了“注释没有用”的问题。

    7.2 使用注释提升系统可维护性

    注释应当能提供代码之外额外的信息,重视What和Why,而不是代码是如何实现的(How),最好不要简单地使用代码中出现过的单词。

    根据抽象程度,注释可以分为低层注释和高层注释,低层次的注释用来增加精确度,补充完善程序的信息,比如变量的单位、控制条件的边界、值是否允许为空、是否需要释放资源等。高层次注释抛弃细节,只从整体上帮助读者理解代码的功能和结构。这种类型的注释更好维护,如果代码修改不影响整体的功能,注释就无需更新。在实际工作中,需要兼顾细节和抽象。低层注释拆散与对应的实现代码放在一起,高层注释一般用于描述接口。

    注释先行,注释应该作为设计过程的一部分,写注释最好的时机是在开发的开始环节,这不仅会产生更好的文档,也会帮助产生好的设计,同时减少写文档带来的痛苦。开发人员推迟写注释的理由通常是:代码还在修改中,提前写注释到时候还得再改一遍。这样的话就会衍生两个问题:

    • 首先,推迟注释通常意味着根本就没有注释。一旦决定推迟,很容易引发连锁反应,等到代码稳定后,也不会有注释这回事。这时候再想添加注释,就得专门抽出时间,客观条件可能不会允许这么做。
    • 其次,就算我们足够自律抽出专门时间去写注释,注释的质量也不会很好。我们潜意识中觉得代码已经写完了,急于开展下一个项目,只是象征性地添加一些注释,无法准确复现当时的设计思路。

    避免重复的注释。如果有重复注释,开发人员很难找到所有的注释去更新。解决方法是,可以找到醒目的地方存放注释文档,然后在代码处注明去查阅对应文档的地址。如果程序已经在外部文档中注释过了,不要在程序内部再注释了,添加注释的引用就可以了。

    注释属于代码,而不是提交记录。一种错误的做法是将功能注释放在提交记录里,而不是放在对应代码文件里。因为开发人员通常不会去代码提交记录里去查看程序的功能描述,很不方便。

    7.3 使用注释改善系统设计

    良好的设计基础是提供好的抽象,在开始编码前编写注释,可以帮助我们提炼模块的核心要素:模块或对象中最重要的功能和属性。这个过程促进我们去思考,而不是简单地堆砌代码。另一方面,注释也能够帮助我们检查自己的模块设计是否合理,正如前文中提到,深模块提供简单的接口和强大的功能,如果接口注释冗长复杂,通常意味着接口也很复杂;注释简单,意味着接口也很简单。在设计的早期注意和解决这些问题,会为我们带来长期的收益。

    八、后记

    John Ousterhout累计写过25万行代码,是3个操作系统的重要贡献者,这些原则可以视为作者编程经验的总结。有经验的工程师看到这些观点会有共鸣,一些著作如《代码大全》、《领域驱动设计》也会有类似的观点。本文中提到的原则和方法具有一定实操和指导价值,对于很难有定论的问题,也可以在实践中去探索。

    关于原则和方法论,既不必刻意拔高,也不要嗤之以鼻。指导实践的不是更多的实践,而是实践后的总结和思考。应用原则和方法论实质是借鉴已有的经验,可以减少我们自行摸索的时间。探索新的方法可以帮助我们适应新的场景,但是新方法本身需要经过时间检验。

    九、参考文档

    • John Ousterhout. A Philosophy of Software Design. Yaknyam Press, 2018.

    • 梅拉尼·米歇尔. 复杂. 湖南科学技术出版社, 2016.

    • Martin Fowler. Refactoring: Improving the Design of Existing Code (2nd Edition) . Addison-Wesley Signature Series, 2018.

    作者介绍

    政华,顺谱,陶鑫,美团打车调度系统工程团队工程师。

    招聘信息

    美团打车调度系统工程团队诚招高级工程师/技术专家,我们的目标,是与算法、数据团队密切协作,建设高性能、高可用、可配置的打车调度引擎, 为用户提供更好的出行体验。欢迎有兴趣的同学加入呦~~

    展开全文
  • 技术系统进化法则_十六种典型创新方法技术进化法则是技术系统为提高自身的有用功能,从一种状态过渡到另一种状态时,系统内部组件之间、系统组件与外界环境间本质关系的体现。即技术系统与生物系统一样,也有一个...
  • 系统工程新发展——体系

    千次阅读 2018-11-09 15:12:13
    系统工程”最早在20世纪40年代由美国贝尔电话公司提出,50年代在美国制造原子弹的“曼哈顿”计划及以后美国北极星导弹和阿波罗登月计划皆为系统工程取得成果的著名范例。中国自20世纪70年代末到80年代在系统工程的...
  • 操作系统(02326)课后习题答案

    千次阅读 多人点赞 2021-12-02 20:28:33
    计算机科学与技术专业 自考本科中操作系统2018版教材的课后习题答案
  • 2014年的618显得和以往任何店庆促销日都不同,不仅仅是因为电子商务本身在中国不断飞速发展对京东系统带来的挑战,更为重要的是2014年5月22日刚走入美国纳斯达克殿堂的京东聚集了最耀眼的光芒,能不能保持这样的光芒...
  • 系统设计的原则、特点与任务

    千次阅读 2020-04-13 18:08:57
    系统设计的原则 根据系统的“吞吐量、响应时间、可靠性、信息处理方式、企业地域范围、数据管理方式”有着不一样的设计 1.吞吐量与软硬件的选择有直接关系,吞吐量越大说明系统的处理能力越强 2.系统的响应时间 3....
  • 适应(domain adaptation)

    千次阅读 多人点赞 2021-05-22 08:52:44
    文章目录导读前言域适应类别任务相关性一步域适应技术及其应用基于散度的域适应基于对抗的域适应基于重建的域适应结论 导读 在迁移学习中, 当源域和目标的数据分布不同 ,但两个任务相同时,这种特殊的迁移学习叫做...
  • 本章节将介绍各类操作系统的特点。 裸机系统 单片机的程序可以分为三种:轮循系统、前后台系统和多任务系统。 轮询系统 即在裸机编程时,先初始化相关硬件,让主程序在一个死循环里面不断循环,顺序地处理各种事件。...
  • 系统复杂度的几个方面

    千次阅读 2018-09-19 10:02:09
    系统与子系统 系统系统是由一群有关联的个体组成的, 规则:系统内的个体需要按照指定的规则运作。规则规定了系统内个体分工和协作的方式。 能力:系统能力与个体能力有本质的差别,系统能力不是个体能力之和,...
  • 操作系统MOOC课后习题答案

    千次阅读 2021-03-25 18:35:21
    1.1 什么是操作系统随堂测验 1、操作系统的核心目标是()。 A、管理硬件 B、运行程序 C、让用户方便使用 D、提高CPU利用率 答案:B 2、从设备到本地缓冲之间传输数据由()完成。 A、I/O控制器 B、CPU C、设备机械...
  • 复杂适应系统和swarm简介

    千次阅读 2004-09-16 21:20:00
    第一部分: 关于swarm.Swarm软件用来给复杂性过个体行为建模, 用于对经济行为的复杂性研究仿真. 他在美国新墨西哥州的 Santa fe 研究所得到开发的。Santa fe 研究所和一些个人及政府为Swarm的发展提供了资助,它的...
  • 大数据+物联网智能交通系统

    千次阅读 2021-11-20 11:22:02
    随着个人奢侈品和就业机会的迅速增加,人们更喜欢自己驾驶汽车来满足他们的交通需求而不是使用公共交通,由于访问的...该系统的设计基于摄像头视频的图像分析,以及在移动设备中使用 GPS 监控特定路线上的交通。如果将
  • VxWorks操作系统基础(适合初学者阅读)

    万次阅读 多人点赞 2019-03-31 18:45:54
    1 实时操作系统概述      1.1 实时操作系统              在计算的早期开发的操作系统的最原始的...
  • 复杂性思维中文第二版 十一、进化

    万次阅读 2018-04-14 12:17:02
    在现实世界中,适应性景观很复杂,但我们不需要建立现实模型。 为了诱导进化,我们需要基因型和适应性之间的某种关系,但事实证明它可以是任何关系。 为了证明它,我们将使用完全随机的适应性景观。 这是代表适应...
  • 图片服务系统是各种针对C端系统常见的子系统,它的特点是存储规模大请求频度高,且单张图片的读请求远远高于写请求。后面几篇文章我们将从图片服务系统的需求分析开始,一起来讨论如何进行这类系统的技术选型、概要...
  • 基于深度学习的推荐系统:综述与新视角

    万次阅读 多人点赞 2018-12-27 10:13:46
    原文:Deep Learning based Recommender System: A Survey and New Perspectives ...推荐系统的效用无论如何强调都不过分,因为它在许多Web应用程序中被广泛采用,以及它对于改善与过度选择相关的许多问题的潜在...
  • 宿舍管理系统

    千次阅读 2022-02-23 19:57:01
    学生宿舍管理系统的设计与实现 DESIGN AND IMPLEMENTATION OF STUDENT DORMITORY MANAGEMENT SYSTEM 姓 名: 张三 学 号: 08220516 班 级: 05软件3 专 业: 计算机 
  • 对于复杂网络解决现实的网络问题

    千次阅读 2018-11-26 22:02:20
    关于复杂网络的应用与发展 复杂网络(Complex networks) 在以往,我们认为网络是通过随机的方式形成的,并且将这些网络成为随机网络,例如在一次马拉松比赛里,参赛人员之间从互相不认识到相互认识,这就是一个随机...
  • 操作系统复习笔记

    万次阅读 多人点赞 2021-01-20 15:11:12
    第一章 计算机系统概述 基本概念 基本构成:处理器、内存、输入/输出模块、系统总线 处理器中各寄存器的作用 处理器分为执行单元、控制单元、寄存器(用户可见寄存器、控制和状态寄存器) 用户可见寄存器 数据...
  • 从前慢-操作系统

    千次阅读 多人点赞 2021-01-03 10:08:57
    1.1操作系统的基本概念 1.1.1操作系统的概念 1.1.2操作系统的特征 1.1.3操作系统的目标和功能 1.2操作系统的发展与分类 1.2.1手工操作阶段(此阶段无操作系统) 1.2.2批处理阶段(操作系统开始出现) 1.2.3分时操作...
  • 操作系统解析

    千次阅读 2019-09-15 17:45:42
    第三节: 操作系统简介3.1 为什么要有操作系统3.2 什么是操作系统3.3 操作系统与普通软件的区别3.4 操作系统发展史3.5 附录及参考资料...
  • 重新思考企业架构

    千次阅读 2022-04-15 01:04:59
    扩展这一类比,企业架构师的角色更类似于城市规划师:定义组织的目标,与其他高级管理者合作制定实现这些目标的策略,为系统开发人员指定约束条件,监控进度和测量结果。正如城市规划师使用的方法和度量标准不同...
  •  伴随着用户群积累,社区的壮大,还有来自投资人对变现渴望的压力,似乎最容易想到的变现途径就是“我们也卖点东西吧”,如果直接给淘宝链接,会显得逼格太低,购买别人的系统,钱不少花,最后为了适应自己的
  • 大数据平台-元数据管理系统解析

    万次阅读 多人点赞 2018-03-14 09:25:24
    在前面的集成开发环境建设相关文章中,我们也提到过,元数据MetaData狭义的解释是用来描述数据的数据,广义的来看,除了业务逻辑直接读写处理的那些业务数据,所有其它用来维持整个系统运转所需的信息/数据都可以叫...
  • 指令系统,寻址方式

    千次阅读 多人点赞 2018-12-23 19:01:52
    用高级语言或者是汇编语言编写的...计算机系统的CPU能够直接识别并且执行的操作命令。一个处理器能够执行的所有的机器指令构成的集合,我们称之为指令集。指令集就是计算机系统软件和硬件的交界面。 软件通过指令系...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 88,618
精华内容 35,447
关键字:

复杂适应系统的例子