软件工程之架构设计
从公众号转载,关注微信公众号掌握更多技术动态
---------------------------------------------------------------
一、架构设计的目的
1.什么是复杂的软件项目
复杂的软件项目通常有两个特点:
-
需求不确定
-
技术复杂
技术的复杂性主要体现在四个方面:
-
需求让技术变复杂:软件要能不断响应新的需求
-
人员让技术变复杂:团队成员水平不一,擅长的技术方向也不一样
-
技术本身复杂:技术本身的使用门槛较高
-
保证软件稳定运行是复杂的:运行时的不确定性
2.软件复杂性
(1)复杂性的表现形式
①症状1-变更放大
变更放大(Change amplification)指得是看似简单的变更需要在许多不同地方进行代码修改。比较典型的代表是Ctrl-CV式代码开发,领域模型缺少内聚与收拢,当需要对某段业务进行调整时,需要改动多个模块以适应业务的发展。
②症状2-认知负荷
认知负荷(Cognitive load)是指开发人员需要多少知识才能完成一项任务。使用功能性框架时,我们希望它操作简单,部署复杂系统时,我们希望它架构清晰,其实都是降低一项任务所需的成本。盲目的追求高端技术,设计复杂系统,增加学习与理解成本都属于本末倒置的一种。
③症状3-未知的未知
未知的未知(Unknown unknowns)是指必须修改哪些代码才能完成任务,或者说开发人员必须获得哪些信息才能成功地执行任务。这一项也是John Ousterhout教授认为复杂性中最糟糕的一个表现形式。
当你维护一个有20年历史的项目时,这种问题的出来相对而言就没那么意外。由于代码的混乱与文档的缺失,导致你无法掌控一个500万行代码的应用,并且代码本身也没有明显表现出它们应该要阐述的内容。这时“未知的未知”出现了,你不知道改动的这行代码是否能让程序正常运转,也不知道这行代码的改动是否又会引发新的问题。这时候我们发现,那些“上帝类”真的就只有上帝能拯救了。
(2) 永远追求最优雅
业务简单的系统不应用DDD架构,弱交互场景也无需进行前后端分离。不要盲从一些教条的观念,选择适合自己的,控制在可控制范围内,既不过度也不缺失。毕竟没有绝对的优雅,甚至没有绝对的正确。
3.架构设计如何解决“复杂”
因为技术的复杂性,会导致软件开发变得很复杂,开发成本高。而架构设计恰恰可以在这些方面很好地解决技术复杂的问题。
主要从四个方面来:
-
架构设计可以降低满足需求和需求变化的开发成本:通过对系统抽象和分解,把复杂系统拆分成若干简单的;对需求的变化,已经有一些成熟的架构实践。
-
架构可以帮助组织人员一起高效协作:通过抽象再拆分,可以把复杂的系统拆分成开发人员可以各自独立完成的模块。
-
架构设计可以帮助组织好各种技术:如分层架构
-
架构设计可以保障服务稳定运行:如分布式架构、异地多活等
-
业务与技术的隔离。以业务为核心,分离业务复杂度和技术复杂度。
-
内部系统与外部依赖的隔离
-
系统中常变部分与不常变部分的隔离
-
隔离复杂性(把复杂性的部分隔离在一个模块,尽量不与其他模块互动)
4.什么是架构设计
架构设计的方法都是基于工程领域分而治之的策略,本质上就是将系统分拆,将人员分拆。但是光拆还不够,拆完了还能拼回来,所以咬清楚架构设计的“道”。
架构设计的道,就是组织人员和技术把系统和团队拆分,并安排好切分后的排列关系,让拆分后的部分能通过约定好的协议互相通信,共同实现最终的结果。
5.如何做好架构设计
业界已经有了很多成熟的架构设计模式,不需要闭门造车,可以在理解清楚业务需求后,找到相近的架构设计,然后基于成熟的架构设计方案,进行改造,变成适合自己业务需求的架构。可以按以下步骤进行。
先模型,再接口,最后 是实现
(1)分析需求
需要对产品需求进一步进行抽象。一个常用的分析方法就是分析用例,也就是了解主要用户校色和其使用的场景。
(2)选择相似的成熟的架构设计方案
在了解清楚需求后,就可以从业界成熟的架构设计模式中选取一个或几个。具体选择 哪些架构设计模式,需要根据平时的学习积累来做判断。
在选好架构方案后,还需要考虑选择什么语言和开发框架。这部分选择需要根据团队情况和项目情况来综合评定。
(3)自顶向下层层细化
从整体到局部,不要过早陷入技术细节中。
①部署架构
②分层和分模块
③模块之间的交互关系
比较常见的系统之间的交互方式有两种,一种是同步接口调用,另一种是利用消息中间件异 步调用。第一种方式简单直接,第二种方式的解耦效果更好。
比如,用户下订单成功之后,订单系统推送一条消息到消息中间件,营销系统订阅订单成功 消息,触发执行相应的积分兑换逻辑。这样订单系统就跟营销系统完全解耦,订单系统不需 要知道任何跟积分相关的逻辑,而营销系统也不需要直接跟订单系统交互。
除此之外,上下层系统之间的调用倾向于通过同步接口,同层之间的调用倾向于异步消息调 用。比如,营销系统和积分系统是上下层关系,它们之间就比较推荐使用同步接口调用。
④API设计、数据库设计、模块设计(业务逻辑)
数据库和接口的设计非常重要,一旦设计好并投入使用之后,这两部分都不能轻易改动。改动数据库表结构,需要涉及数据的迁移和适配;改动接口,需要推动接口的使用者作相应的 代码修改。这两种情况,即便是微小的改动,执行起来都会非常麻烦。因此,在设计接 口和数据库的时候,一定要多花点心思和时间,切不可过于随意。相反,业务逻辑代码侧重 内部实现,不涉及被外部依赖的接口,也不包含持久化的数据,所以对改动的容忍性更大。
(4)验证和优化架构设计方案
二、设计文档
1.概要设计
在概要设计阶段,一般以子系统为维度来阐述系统各个角色之间的关系。对于关键的子 系统,还会进一步分解它,甚至详细到把该子系统的所有模块的职责和接口都确定下 来。
这个阶段的核心意图并不是确定系统完整的模块列表,焦点是整个系统如何被有 效地串联起来。如果某个子系统不做进一步的分解也不会在项目上有什么风险,那么并 不需要在这个阶段对其细化。
为了降低风险,概要设计阶段也应该有代码产出。 这样做的好处是,一上来我们就关注了全局系统性风险的消除,并且给了每个子系统或模块 的负责人一个更具象且确定性的认知。 代码即文档。代码是理解一致性更强的文档。 经过系统的概要设计,整个系统的概貌就了然于胸了。
2.详细设计
详细设计阶段,是需要各个子系统或 模块的负责人,对他负责的部分进行进一步的细化。详细设计关注的是子系统或模块的全貌。概要设计不一定会把子系统或模块的完整接口都列出来, 实际上它只关注最核心的部分。但是从详细设计角度来说,接口描述的完备性是必需的。 详细设计并不是只谈实现就完事,更不是一个架构图。它包括以下这些内容。
(1)现状与需求
现在在哪里,遇到了什么问题,要做何改进。从逻辑自洽的角度,任何一篇文档,首先关注的都应该是要解决的问题与目标。 现状与需求的陈述,要简明扼要。 现状更多的是陈述与我们要做的改变相关的重要事实,侧 重点在于强调这些事实的存在性和重要性。 假设要对某个模块重构。那么,现状就是要谈清楚现在的业务架构是怎样的?它 到底有什么样的问题。
需求陈述是对痛点和改进方向的一次共识确认。痛点只要够痛,大家都知道,所以同样不需 要长篇累牍。 每个子系统或模块,都有自己的角色分工与用户故事。不用重新做一遍需求分析,但对 需求分析的核心结论,在详细设计开始之前需要明确。 这很重要。它是我们详细设计所要满足的业务目标。
(2)需求满足方式
要做成啥样?交付物的规格,或者说使用界面(接口)。规格,或者说使用界面,体现的是别人要怎么使用。 使用界面(接口)应该自然体现业务需求,就是强调程序是为用户需 求服务的。而架构设计,在需求分析与后续的概要设计、详细设计等过程之间也要有 自然的延续性。
使用界面这一部分要详细写,它是团队共识确认的关键。 我们的交付物有哪些可执行文件,有哪些包(package)?如果可执行文件,那么它是一个 界面程序,还是服务?如果是服务,网络协议是什么样的?如果是包,它又包含哪些公开的 类或函数。
更需要强调的是,使用界面的稳定是至关重要的。对使用界面的不兼容调整,可能出现严重的后果。技术上,可能会导致客户异常,出现编译
失败需要重写代码,或者更严重的是,可能导致他们的系统崩溃。商业上,则可能导致大量 的客户流失。接口的变更需谨慎!
没有页面写接口得变更
(3)程序 = 数据结构 + 算法
①数据结构
数据结构从大的层面分,可分为基于内存的数据结构,和基于外存(比如 SSD 盘)的数据 结构。在服务端我们谈数据结构,谈的不是内存数据结构,往往谈的是数据库的表结构设计。
不管我们用的是哪种数据库,出于惯例我们往往还是以 “定义表结 构” 一词来表达想干什么。其实定义表结构和定义内存数据结构本质是完全一致的。定义内存中的一个类 (或结构体),我们也关心字段名(成员变量名)和类型,也关心字段的含义,以及它是否 指向另一个类(或结构体)的某个字段(成员变量)。
②算法
在架构过程中,需求分析阶段,我们关注用户需求的精确表述,会引入 角色,也就是系统的各类参与方,以及角色间的交互方式,也就是用户故 事。 到了详细设计阶段,角色和用户故事就变成了子系统、模块、类或者函数的 使用界面(接口)。使用界面(接口)应该自然体现 业务需求,就是强调程序是为用户需求服务的。而我们的架构设计,在需求 分析与后续的概要设计、详细设计等过程之间也有自然的延续性。 所以算法,最直白的含义,指的是用户故事背后的实现机制。
那么,怎么描述一个用户故事对应的算法?
-
基于 UML 时序图(Sequence Diagram)。
-
基于伪代码(Pseudo Code)。在逻辑较为复杂时,伪代码往往有更好的呈
-
现效果。
三、如何做好技术选型
1.项目决策
(1)问题定义
问题定义阶段需要明确两个问题:
-
为什么需要技术选型
-
技术选型目标是什么
只有明确了技术选型的目标,才有一个标准来评判该选择哪一个方案。
(2)调研
在明确技术选型的目标后,需要进行调研看有哪些技术选型可以满足目标,可以从这几个方面去分析:
-
是否满足技术选型目标
-
是否满足时间、范围和成本的约束
-
是否可行
-
有什么样的风险?是否可控
-
优缺点是什么
(3)验证
可以通过一个快速原型项目,用候选技术方案快速做一个原型出来,做的过程中才知道,所做的技术选型是否真的满足技术选型的目标。
(4)决策
在调研和验证完成后,需要召集所有利益相关人一起,就选择的方案做一个调研结果评审的会议,做出最终的决策。
2.架构思维
架构设计是要控制技术的复杂性。对于架构师来说,要控制技术复杂性,有几种有效的方式:抽象、分治、复用和迭代。架构师思维其实就是这几种思维的集合。
-
抽象思维:对需求进行抽象建模后,可以帮助我们隐藏很多无关紧要的细节,在高层次的架构设计时,可以关注在几个主要的模型上,而不必关心模型内的细节实现。
-
分治思维:架构设计的一个重点,就是要对复杂系统分而治之。
-
复用思维:通过对相同内容的抽象,让其能复用于不同的场景,是一种非常简单的提升开发效率的方法。
-
迭代思维:好的架构通常不是一步到位,而是先满足好当前业务需求,然后随着业务的变化而逐步演进。
3.架构选型这注意点
(1)产品选型要服从于项目整体目标
局部最优的选择拼装在一起未必是全局最优的方案。如果你的目标是要对整个应用系统做彻底重构,例如把单体架构改为微服务架构,那么要解决原来某些局部的问题,可能会有 更多选择。这时候要从整体上评估技术复杂度、工程实施等因素,而不是仅选择局部最合 理的方案。
(2)先进的产品可能会延长项目交付时间
最先进的产品不一定是完美的选择。尤其是有进度要求时,往往会选择更稳妥、快速的办 法。但是,这本质上是在短期利益和长期利益之间做权衡,没有绝对的对错,搞清楚你想要的是什么就行。
(3)当产品选型可能导致业务流程变更时,请慎重对待
对任何项目来说,协作范围的扩大一定会增加实施难度。当技术部门对业务流程变更没有决定权时,我认为这是多数情况,通过技术手段避免这种变更往往是更好的选择。
(4)评估技术潮流对选型影响
跟随潮流并不是人云亦云,你必须能够独立对技术发展趋势做出研判。太过小众的技术往 往不能与工程化要求兼容。但同时,保持对新技术的敏感度和掌控力,也是非常必要的。
四、技术债务
1.什么是技术债务
范围不减、成本不加,还想节约时间,就会影响到质量。技术债务就是软件项目中对架构质量和代码质量的透支。
技术债务具有以下特点:
-
有利息:后期对软件做修改的时候,需要额外的时间成本。
-
不一定都是坏的:如快速原型模型,就是通过技术债务的方式快速开发快速验证。验证不可行,则无需偿还债务。
2.如何管理
技术债务有利息也有收益,如何管理才能保证软件项目中的收益大于支付的利息。
(1)识别债务
软件项目中有很多指标来发现存在的技术债务:
-
开发速度降低
-
单元测试覆盖率低
-
代码规范检查的错误率高
-
Bug数量越来越多
(2)处理技术债务策略
在识别之后,解决技术债务有三种策略:
-
重写:推翻重来,一次还清
-
维持:修修补补,只还利息。适用于不需要增加新功能的系统
-
重构:新旧交替,分期付款
(3)实施策略
-
重写-正式项目来立项
-
重构-将任务拆分并进行跟踪
-
维持-制定计划
(4)预防
最好的方法是预防技术债务的产生:
-
预先投资:好的架构,高质量的代码是一种技术投资
-
不走捷径:做好代码审查、保障单元测试代码覆盖率等
-
及时还债:记下欠的债务,及时还债。
相关文章:
软件工程之架构设计
从公众号转载,关注微信公众号掌握更多技术动态 --------------------------------------------------------------- 一、架构设计的目的 1.什么是复杂的软件项目 复杂的软件项目通常有两个特点: 需求不确定 技术复杂 技术的复杂性主要体现在四个方面…...
oracle java.sql.SQLException: Invalid column type: 1111
1.遇到的问题 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{propertyuuid, modeIN, javaTypeclass java.lang.String, jdbcTypenull, numericScalenull, r…...
Mac 浏览器下载的文件名总是「乱码」
如果可以实现记得点赞分享,谢谢老铁~ 本文所说的方法是在出现文件名乱码情况下,如何恢复文件名的正确中文名称,并非一劳永逸地避免乱码的出现。这是由于下载文件名称乱码的出现,往往是系统、浏览器、网站三方面因素共…...
Redis Reactor事件驱动模型源码
前置学习:Redis server启动源码-CSDN博客 1、Redis服务器启动的时候就会就一直在轮询。 // 运行事件处理器,一直到服务器关闭为止 aeSetBeforeSleepProc(server.el,beforeSleep); aeMain(server.el);// 服务器关闭,停止事件循环 aeDeleteEven…...
cv2.error: OpenCV(4.7.0)
运行hsv脚本报错: cv2.error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function cv::cvtColor 解决方案: 这个错误信息是在使用OpenCV的cvtColor函…...
10.vue3项目(十):spu管理页面的sku的新增和修改
目录 一、sku静态页面的搭建 1.思路分析 2.代码实现 3.效果展示...
Java LeetCode篇-深入了解二叉树经典解法(三种方式实现:获取二叉树的最大深度)
🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 对称二叉树 1.1 判断对称二叉树实现思路 1.2 代码实现:判断对称二叉树 2.0 二叉树的最大深度 2.1 使用递归实现获取二叉树的最大深度思路 2.2 代码实…...
Image Segmentation Using Deep Learning: A Survey
论文标题:Image Segmentation Using Deep Learning:A Survey作者:发表日期:阅读日期 :研究背景:scene understanding,medical image analysis, robotic perception, video surveillance, augmented reality, and image…...
可视化开源编辑器Swagger Editor本地部署并实现远程访问管理编辑文档
最近,我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念,而且内容风趣幽默。我觉得它对大家可能会有所帮助,所以我在此分享。点击这里跳转到网站。 文章目录 Swagger Editor本地接口文档公网远程访问1. 部署Swagge…...
Java TCP协议实现一对一聊天与UDP协议实现群聊案例
JavaTCP协议实现一对一聊天与UDP协议实现群聊案例 1.TCP协议实现一对一聊天 1.1服务端运行结果 1.2客服端运行结果 1.3代码汇总 服务端 package twentyone;import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.…...
【从0配置JAVA项目相关环境1】jdk + VSCode运行java + mysql + Navicat + 数据库本地化 + 启动java项目
从0配置JAVA项目相关环境 写在最前面一、安装Java的jdk环境1. 下载jdk2. 配置jdk3. 配置环境变量 二、在vscode中配置java运行环境1. 下载VSCode2. 下载并运行「Java Extension Pack」 三、安装mysql1.官网下载MySQL2.开始安装如果没有跳过安装成功 3.配置MySQL Server4.环境变…...
人工智能_机器学习053_支持向量机SVM目标函数推导_SVM条件_公式推导过程---人工智能工作笔记0093
然后我们再来看一下支持向量机SVM的公式推导情况 来看一下支持向量机是如何把现实问题转换成数学问题的. 首先我们来看这里的方程比如说,中间的黑线我们叫做l2 那么上边界线我们叫l1 下边界线叫做l3 如果我们假设l2的方程是上面这个方程WT.x+b = 0 那么这里 我们只要确定w和…...
二叉树的前、中和后序遍历的递归与迭代实现
1. 前序遍历 1.1 递归 /*** Definition for a binary tree node.* function TreeNode(val, left, right) {* this.val (valundefined ? 0 : val)* this.left (leftundefined ? null : left)* this.right (rightundefined ? null : right)* }*/ /*** param …...
人体姿态估计算法
人体姿态估计算法 1 什么是人体姿态估计2 基于经典传统和基于深度学习的方法2.1 基于经典传统的人体姿态估计算法2.2 基于深度学习的人体姿态估计算法OpenPoseAlphaPose (RMPE) 3 算法应用4 Paper 人体姿态估计在现实中的应用场景很丰富,如下 动作捕捉:三…...
docker部署jupyter
文章目录 1.搜索镜像2.拉取镜像3.创建挂载4.运行容器4.查看容器运行运行状态5.token查看6.访问jupyter 1.搜索镜像 docker search jupyter: 命令用于在 Docker Hub 上搜索名为 “jupyter” 的镜像。搜索结果显示了一个名为 “jupyter/datascience-notebook” 的镜像࿰…...
音视频的功耗优化
前言 在应用中,录制与音视频模块往往是高耗能的模块,设备容易发热,影响体验。 什么是功耗优化 手机有多个耗电模块, SOC(CPU,GPU,DDR),Display,Audio,Video࿰…...
Python实现FA萤火虫优化算法优化XGBoost回归模型(XGBRegressor算法)项目实战
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法(Fire-fly algorithm,FA)由剑桥大学Yang于2009年提出 , …...
SCAUoj综合性实验
Last One ! 文章目录 1109 综合实验:文件操作与字符处理总结 1109 综合实验:文件操作与字符处理 时间限制:4000MS 代码长度限制:10KB 提交次数:6265 通过次数:1646 题型: 填空题 语言: GCC Description 在当前目录中存在文件名为"case1.in"&…...
智加科技获全国首张重卡无人驾驶开放道路测试牌照
2023年12月1日,智加科技获得苏州市智能网联汽车无人化测试牌照。该牌照也是江苏省及国内首张无人重卡开放高速公路全路段全场景全息路网(S17苏台高速)道路测试牌照。 该重卡无人驾驶开放道路测试牌照,经由苏州市智能网联汽车联席小…...
LLM大语言模型(一):ChatGLM3-6B本地部署
目录 前言 本机环境 ChatGLM3代码库下载 模型文件下载 修改为从本地模型文件启动 启动模型网页版对话demo 超参数设置 GPU资源使用情况 (网页对话非常流畅) 前言 LLM大语言模型工程化,在本地搭建一套开源的LLM,方便后续的…...
chatgpt prompt提示词
chatgpt的接口是一个标准的http请求,请求的url为 POST https://api.openai.com/v1/chat/completions 官方的接口文档地址为:https://platform.openai.com/docs/api-reference/chat/create Example request curl https://api.openai.com/v1/chat/comp…...
【PyTorch】数据集
文章目录 1. 创建数据集1.1. 直接继承Dataset类1.2. 使用TensorDataset类 2. 数据集的划分3. 加载数据集4. 将数据转移到GPU 1. 创建数据集 主要是将数据集读入内存,并用Dataset类封装。 1.1. 直接继承Dataset类 必须要重写__getitem__方法,用于根据索…...
oops-framework框架 之 本地存储(五)
引擎: CocosCreator 3.8.0 环境: Mac Gitee: oops-game-kit 注: 作者dgflash的oops-framework框架QQ群: 628575875 简介 在CocosCreator中,本地存储主要使用sys.localStorage 接口,通过 key-value的格式进…...
编程常见的问题
在现代社会中,编程已经成为一项非常重要的技能。随着科技的不断发展和普及,计算机已经渗透到我们生活的方方面面,从个人电脑、手机到智能家居、自动驾驶等。编程作为计算机科学的基础,为我们提供了解决问题和创造新事物的工具和方…...
针对Arrays.asList的坑,可以有哪些处理措施
上文讲述:Error querying database. Cause: java.lang.reflect.InaccessibleObjectException: 那么如果真的只习惯用Arrays.asList,那也是有对应的解决办法的。 一、解决办法大方向 不管做什么事情,都是先判定一个大方向,不管是…...
SE考研真题总结(一)
本帖开始分享考研真题中设计【软件工程】的部分,预计会出5期左右,敬请期待~ 一.单选题 1.程序编写不是软件质量保障过程~ 静态代码扫描是今年来多数被人提及的软件应用安全解决方案之一,指程序员在编写好代码后无需进行编译,直接…...
Xshell远程登录AWS EC2 Linux实例
文章目录 小结问题解决参考 小结 Xshell远程登录AWS EC2 Linux实例碰到些问题,进行解决并记录。 问题 在AWS中创建 EC2 Linux实例,生成的非对称密钥对,使用Xshell远程登录碰到一些问题。 解决 首先在Putty中可以使用的ppk密钥文件在Xshe…...
Elasticsearch:对时间序列数据流进行降采样(downsampling)
降采样提供了一种通过以降低的粒度存储时间序列数据来减少时间序列数据占用的方法。 指标(metrics)解决方案收集大量随时间增长的时间序列数据。 随着数据老化,它与系统当前状态的相关性越来越小。 降采样过程将固定时间间隔内的文档汇总为单…...
python自动化测试框架:unittest测试用例编写及执行
本文将介绍 unittest 自动化测试用例编写及执行的相关内容,包括测试用例编写、测试用例执行、测试报告等内容。 官方文档: https://docs.python.org/zh-cn/3/library/unittest.mock.html 1. 测试用例编写 在 unittest 中,一个测试用例通常…...
ctfhub技能树_web_web前置技能_HTTP
目录 一、HTTP协议 1.1、请求方式 1.2、302跳转 1.3、Cookie 1.4、基础认证 1.5、响应包源代码 一、HTTP协议 1.1、请求方式 注:HTTP协议中定义了八种请求方法。这八种都有:1、OPTIONS :返回服务器针对特定资源所支持的HTTP请求方法…...
建造师免费自学网站/夸克搜索引擎入口
由于之前一直用eclipse/dev之类的写C/C程序,今天开始慢慢转为用VS替代eclipse进行C/C的开发了。首篇总结下一下基础的小技巧或者说常识。 1:stdafx.h是什么鬼,就是使编译出来的程序能够在32位机器运行(win32)…...
wordpress域名资源地址/保定百度首页优化
QStyle(5):QStyle枚举综合 本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇) 本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址: https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q 《C语法…...
做旅游网站的目的和意义/seo有什么作用
一般情况下,建议使用矢量工具来创建签名或水印,这样可以保证签名图形任意缩放而不失真。但普通的摄影爱好者如果不太擅长使用矢量工具,可考虑下面的画笔预设法或动作法来给自己的照片添加签名,亦可满足日常出片需要。◆ ◆ ◆方…...
网站建设技术规范/网络推广和网站推广平台
import java.util.Calendar; import java.util.Scanner; /* * 获取任意一年的二月有多少天 * * 分析: * A:键盘录入任意的年份 * B:设置日历对象的年月日 * 年就是A输入的数据 * 月是2 * 日是1 * C:把时间往前推一天,就是2月的最后一天 * D:…...
乔拓云智能建站系统官网/搜索seo优化
本节书摘来自异步社区《设计之外——比修图更重要的111件事》一书中的第1部分1惊天大秘密,作者【美】Michael Janda,更多章节内容可以访问云栖社区“异步社区”公众号查看。 第一部分 为人处事设计之外——比修图更重要的111件事想要获得成功,你的言谈举…...
网站运营做seo/有没有推广app的平台
整数运算 无符号加法 两个非负整数的加法很有可能会导致溢出 两数相加后,丢弃超越范围的数字,得到的结果类似于模运算 例如9 12 .21 [10101] > [0101] 5 21 % 16 丢弃最高位相当于从和中减去2^w(无符号) C语言不会因为溢出而发出信号 检测…...