自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(70)
  • 收藏
  • 关注

原创 C语言位操作

【代码】C语言位操作。

2022-12-25 20:47:46 219

原创 QTableView如何设置表头宽度

QTableView如何设置表头宽度

2022-10-10 23:04:59 4388

原创 C++ enum前置声明

枚举在C++有两种形式,enum和enum class,enum是C++11之前的写法,也就是无范围枚举,enum class是C++11引入的,既有范围的枚举。

2022-08-05 21:26:44 2300

原创 QSlider美化规则

QSlider展示大概有两种,一种是handle在那个滑动槽内,一种是handle大于滑动槽。

2022-07-24 13:31:17 557

原创 QWidget setStyleSheet无效

在项目中,我们发现继承QWidget的子类在setStyleSheet时在QtDesigner里面看好好的,但是实际运行起来,发现设置的效果并没有展示出来。

2022-07-24 12:36:09 1237

原创 Qt arcTo函数

Qt arcTo函数详解

2022-07-03 11:57:46 1759

原创 Qt High DPI解决方案

1.不完美的方案使用Qt:AA_EnableHighDpiScaling。100%和125%程序没缩放,150%程序会变大两倍,不符合预期。使用PROCESS_DPI_UNAWARE。程序确实按照DPI缩放了,但是画面变模糊了。2.完美的方案一个完美的方案,必须是程序的尺寸能和DPI对应上,而且画面不模糊。2.1 注意点如果你的程序是结合OpenGL程序的,你需要小心,如果OpenGL是在Qt程序里面写的话,可能不会有太大的问题,但是如果OpenGL功能是由别人提供的,像自己封装成一个库,那

2022-05-27 22:30:53 4174

原创 解决Win7安装C++ Redistributable2015失败

1.查看Windows版本1.1.在开始菜单,输入winver,然后回车1.2. 如果版本是7601,可跳过步骤2,如果版本是7600,则需要安装补丁升级系统到76012.升级系统到7601版本2.1. 下载补丁2.2 下载完安装,然后重启,就可以升级到76013.安装Visual C++ 2015-2019 Redistributablex86x64...

2021-10-14 14:18:19 5245 6

原创 代码的坏味道

Duplicated Code(重复的代码)坏味道行列中首当其冲的就是Duplicated Code。如果你在一个以上的地点看到相同的程序结构,那么可以肯定:设法将它们合而为一,程序会变得更好。最单纯的Duplicated Code就是“同一个类的两个函数含有相同的表达式”。这时候你需要做的就是采用Extract Method提炼出重复的代码,然后让这两个地点都调用被提炼出来的那一段代码。另一种常见的情况就是“两个互为兄弟的子类内含相同的表达式”。要避免这种情况,只需对两个类都是用Extract Me

2021-09-16 15:04:02 1167 1

原创 Push Down Field(字段下移)

动机Push Down Field与Pull Up Field恰恰相反;如果只有某些(而非全部)子类需要超类内的一个字段,你可以使用本项重构。做法在所有子类中声明该字段。将该字段从超类中移除。编译,测试。将该字段从所有不需要它的那些子类中删除。编译,测试。范例重构后...

2021-08-23 16:40:49 202

原创 Push Down Method(函数下移)

动机Push Down Method与Pull Up Method恰恰相反。当我有必要把某些行为从超类移至特定的子类时,我就使用Push Down Method,它通常也只有这种时候有用。使用Extract Subclass之后你可能会需要它。做法在所有子类中声明该函数,将超类中的函数本体复制到每一个子类函数中。删除超类中的函数。2.1. 你可能必须修改调用端的某些变量声明或参数声明,以便能够使用子类。2.2. 如果有必要通过一个超类对象访问该函数,或你不想把该函数从任何子类中移除,再或超类是

2021-08-21 10:44:25 538

原创 Pull Up Constructor Body(构造函数本体上移)

动机如果你看见各个子类中的函数有共同行为,第一个念头应该是将共同行为提炼到一个独立函数中,然后将这个函数提升到超类。对构造函数而言,它们彼此的共同行为往往就是“对象的建构”,这时候你需要在超类中提供一个构造函数,然后子类都来调用它。很多时候,子类构造函数的唯一动作就是调用超类构造函数。这里不能运用Pull Up Method,因为你无法在子类中继承超类构造函数。如果重构过程过于复杂,你可以考虑转而使用Replace Constructor with Factory Method。做法在超类中定义一

2021-08-20 10:58:32 429

原创 Pull Up Method(函数上移)

动机避免行为重复是很重要的。尽管重复的两个函数也可以各自工作得很好,但重复自身只会成为错误的滋生地,此外别无价值。无论何时,只要系统之内出现重复,你就会面临“修改其中一个却未能修改另一个”的风险。通常,找出重复也有一定困难。如果某个函数在各个子类中的函数体都相同(它们很可能是通过复制粘贴得到的),这就是最显而易见的Pull Up Method适用场合。当然,情况并不总是如此明显。你也可以只管放心地重构,再看看测试程序会不会发牢骚,但这就需要对你的测试有充分的信心。我发现,观察这些可能重复的函数之间的差异

2021-08-19 10:27:44 845

原创 Pull Up Field(字段上移)

动机如果各子类时分别开发的,或者是在重构过程中组合起来的,你常会发现它们拥有重复特性,特别是字段更容易重复。这样的字段有时拥有近似的名字,但也并非绝对如此。判断若干字段是否重复,唯一的办法就是观察函数如何使用它们。如果它们被使用的方式很相似,你就可以将它们归纳到超类去。本项重构从两方面减少重复:首先它去除了重复的数据声明:其次它使你可以将使用该字段的行为从子类移至超类,从而去除重复的行为。做法针对待提升之字段,检查它们的所有被调用点,确认它们以同样的方式被使用。如果这些字段的名称不同,先将它们改

2021-08-18 10:36:01 308

原创 Replace Constructor with Factory Method(以工厂函数取代构造函数)

动机使用该项重构的最显而易见的动机,就是在派生子类的过程中以工厂函数取代类型码。你可能常常需要根据类型码创建相应的对象,现在,创建名单上还得加上子类,那些子类也是根据类型码来创建。然而由于构造函数只能返回单一类型的对象,因此你需要将构造函数替换为工厂函数。此外,如果构造函数的功能不能满足你的需要,也可以使用工厂函数来代替它。工厂函数也是Change Value to Reference的基础。你也可以令你的工厂函数根据参数的个数和类型,选择不同的创建行为。做法新建一个工厂函数,让它调用现在的构造函

2021-08-17 10:37:58 591

原创 Encapsulate Downcast(封装向下转型)

动机在强类型OO语言中,向下转型是最烦人的事情之一。之所以很烦人,是因为从感觉上来说它完全没有必要:你竟然越俎代庖地告诉编译器某些应用由编译器自己计算出来的东西。但是,由于计算对象类型往往比较麻烦,你还是常常需要亲自告诉编译器对象的确切类型。向下转型在java特别盛行,因为java没有模板机制,因此如果你想从集合之中取出一个对象,就必须进行向下转型。向下转型也许是一种无法避免的罪恶,但你仍然应该尽可能少做。如果你的某个函数返回一个值,并且你知道所返回的对象类型比函数签名所昭告的更特化,你便是在函数用户身

2021-08-16 11:36:41 199

原创 Hide Method(隐藏函数)

动机重构往往促使你修改函数的可见度。提高函数可见度的情况很容易想象:另一个类需要用到某个函数,因此你必须提高该函数的可见度。但是要指出一个函数的可见度是否过高,就稍微困难一些。理想状态下,你可以使用工具检查所有函数,指出可被隐藏起来的函数。即使没有这样的工具,你也可以进行这样的检查。一种特别常见的情况是:当你面对一个过于丰富、提供了过多行为的接口时,就值得将非必要的取值函数和设值函数隐藏起来。尤其当你面对的是一个只有简单封装的数据容器时,情况更是如此。随着越来越多行为被放入这个类,你会发现许多取值/设值

2021-08-15 11:06:16 277

原创 Remove Setting Method(移除设值函数)

动机如果你为某个字段提供了设值函数,这就暗示这个字段值可以被改变。如果你不希望在对象创建之后此字段还有机会被改变,那就不要为它提供设值函数(同时将该字段设为final)。这样你的意图会更加清晰,并且可以排除其值被修改的可能性——这种可能性往往是非常大的。如果你保留了间接访问变量的方法,就可能经常有程序员盲目使用它们。这些人甚至会在构造函数中使用设值函数!我猜想他们或许是为了代码的一致性,但却忽视了设值函数往后可能带来的混淆。做法检查设值函数被使用的情况,看他是否只被构造函数调用,或者被构造函数所调

2021-08-14 15:55:25 264

原创 Replace Parameter with Method(以函数取代参数)

动机如果函数可以通过其他途径获得参数值,那么它就不应该通过参数取得该值。过长的参数列会增加程序阅读者的理解难度,因此我们应该尽可能缩短参数列的长度。缩减参数列的办法之一就是:看看参数接收端是否可以通过与调用端相同的计算来取得参数值。如果调用端通过其所属对象内部的另一个函数来计算参数,并在计算过程中未曾引用调用端的其他参数,那么你就应该可以将这个计算过程转移到被调用端内,从而去除该项参数。如果你所调用的函数隶属另一个对象,而该对象拥有调用端所属对象的引用,前面所说的这些也同样适用。但是,如果参数值的计算

2021-08-13 11:19:54 473

原创 Preserve Whole Object(保持对象完整)

动机有时候,你会将来自同一对象的若干项数据作为参数,传递给某个函数。这样做的问题在于:万一将来被调用函数需要新的数据项,你就必须查找并修改对此函数的所有调用。如果你把这些数据所属的整个对象传给函数,可以避免整个尴尬的处境,因为被调用函数可以向那个参数对象请求任何它想要的信息。除了可以使参数列更稳固之外,Preserve Whole Object往往还能提高代码的可读性。过长的参数列很难使用,因为调用者和被调用者都必须记住这些参数的用途。此外,不使用完整对象也会造成重复代码,因为被调用调用函数无法利用完整

2021-08-11 11:03:55 551

原创 Parametaerize Method(令函数携带参数)

动机你可能会发现这样的两个函数:它们做着类似的工作,但因少数几个值致使行为略有不同。在这种情况下,你可以将这些各自分离的函数统一起来,并通过参数来处理那些变化情况,用以简单问题。这样的修改可以去除重复的代码,并提高灵活性,因为你可以用这个参数处理更多的变化情况。做法新建一个带有参数的函数,使它可以替换先前所有的重复性函数。编译。将调用旧函数的代码改为调用新函数。编译,测试。对所有旧函数重复上述步骤,每次替换后,修改并测试。范例class Employee { void tenPerc

2021-08-09 11:18:54 199

原创 Separate Query from Modifier(将查询函数和修改函数分离)

动机如果某个函数只是向你提供一个值,没有任何看得到的副作用,那么这是个很有价值的东西。你可以任意调用这个函数,也可以把调用动作搬到函数的其他地方。简而言之,需要操心的事情少多了。明确表现出“有副作用”与“无副作用”两种函数之间的差异,是个很好的想法。下面是一条好规则:任何有返回值的函数,都不应该有看得到的副作用。有些程序员甚至将此作为一条必须遵守的规则。就像对待任何东西一样,我并不绝对遵守它,不过我总是尽量遵守,而它也回报我很好的效果。做法新建一个查询函数,令它返回的值与原函数相同。修改原函数,

2021-08-08 11:29:17 297

原创 Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件表达式)

动机根据我的经验,条件

2021-08-03 20:00:57 164

原创 Consolidate Duplicate Conditional Fragments(合并重复的条件片段)

动机有时你会发现,一组条件表达式的所有分支都执行了相同的某段代码。如果是这样,你就应该将这段代码搬移到条件表达式外面。这样,代码才能更清楚地表明那些东西随条件的变化而变化、哪些东西保持不变。做法鉴别出“执行方式不随条件变化而变化”的代码。如果这些共通代码位于条件表达式起始处,就将它移到条件表达式之前。如果这些共通代码位于条件表达式尾端,就将它移到条件表达式之后。如果这些共通代码位于条件表达式中段,就需要观察共通代码之前或之后的代码是否改变了什么东西。如果的确有所改变,应该首先将共通代码向前或向

2021-07-30 09:28:56 316

原创 Consolidate Conditional Expression(合并条件表达式)

动机有时你会发现这样一串条件检查:检查条件各不相同,最终行为却一致。如果发现这种情况,就应该使用“逻辑或”和“逻辑与”将它们合并成为一个条件表达式。之所以要合并条件代码,有两个重要的原因。首先,合并后的条件代码会告诉你“实际上只有一次条件检查”,只不过有多个并列条件需要检查而已“,从而使这一次检查的用意更清晰。当然,合并前和合并后的代码有着相同的效果,但原先代码传达出的信息却是”这里有一些各自独立的条件测试,它们知识恰好同时发生“。其次,这项重构往往可以为你使用Extract Method做好准备。将检

2021-07-29 15:43:35 335

原创 Decompose Conditional(分解条件表达式)

动机程序之中,复杂得条件逻辑是最常导致复杂度上升得地点之一。你必须编写代码来检查不同的条件分支、根据不同的分支做不同的事,然后,你很快就会得到一个相当长的函数。大型函数自身就会使代码的可读性下降,而条件逻辑则会使代码更难阅读。在带有复杂条件逻辑的函数中,代码(包括检查条件分支的代码和真正实现功能的代码)会告诉你发生的事,但常常让你弄不清楚为什么会发生这样的事,这就说明代码的可读性的确大大降低了。和任何大块代码一样,你可以将它分解为多个独立函数,根据每个小块代码的用途,为分解而得的新函数命名,并将原函数中

2021-07-28 19:11:49 334

原创 Encapsulate Collection(封装集合)

动机我们常常会在一个类中使用集合(可能是array、list、set或vector)来保存一组实例。这样的类通常也会提供针对该集合的取值/设值函数。但是,集合的处理方式应该和其他种类的数据略有不同。取值函数不该返回集合自身,因为这会让用户得以修改集合内容而集合拥有者却一无所悉。这也会对用户暴露过多内部数据结构的信息。如果一个取值函数确实需要返回多个值,它应该避免用户直接操作对象内所保存的集合,并隐藏对象内于用户无关的数据结构。另外,不因该为整个集合提供一个设值函数,但应该提供用以为集合添加/移除元素的

2021-07-24 10:23:06 218 1

原创 Encapsulate Field(封装字段)

动机面向对象的首要原则之一就是封装,或者称为“数据隐藏”。按此原则,你绝不应该将数据声明为public,否则其他对象就有可能访问甚至修改这项数据,而拥有该数据的对象却毫无察觉。于是,数据和行为就被分开了——这可不是件好事。数据声明为public被看作是一种不好的做法,因为这样会降低程序的模块化程度。数据和使用该数据的行为如果集中在一起,一旦情况发生变化,代码的修改就会比较简单,因为需要修改的代码都集中于同一块地方,而不是星罗棋布地散落在整个程序中。做法为public字段提供取值/设值函数。找到这

2021-07-23 10:20:08 400

原创 Replace Magic Number with Symbolic Constant(以字面常量取代魔法数)

动机在计算机科学中,魔法数是历史最悠久得不良现象之一。所谓魔法数是指拥有特殊意义,却又不能明确表现出这种意义得数字。如果你需要在不同的地方引用同一个逻辑数,魔法数会让你烦恼不已,因为一旦这些数发生变化,你就必须在程序中找到所有魔法数,并将它们全部修改一遍,这简直就是一场噩梦。就算你不需要修改,要准确找出每个魔法数的用途,也会让你颇费脑筋。许多语言都允许你声明变量。变量不会造成任何性能开销,却可以大大提高代码的可读性。做法声明一个常量,令其值为原本的魔法数值。找出这个魔法数的所有引用点。检查是否

2021-07-21 09:45:58 341

原创 Replace Array with Object(以对象取代数组)

动机数组是一种常见的用以组织数据的结构。不过,它们应该只用于“以某种顺序容纳一组相似对象”。有时候你会发现,一个数组容纳了多种对象,这会给用户带来麻烦,因为他们很难记住像”数组的第一个元素是人名“这样的约定。对象就不同了,你可以运用字段名称和函数来传达这样的信息,因此你无须死记它,也无须依赖注释。做法新建一个类表示数组所拥有的信息,并在其中以一个public字段保存原先数组。修改数组的所有用户,让它们改用新类的实例。编译,测试。逐一为数组元素添加取值/设值函数。根据元素的用途,为这些访问函数命

2021-07-18 10:40:07 199

原创 软件开发和服务项目价格构成及评估方法

(中国软件行业协会发布)该估算方法,不是物价部门的定价,仅为软件开发价格、软件(系统)维护收费价格、系统集成价格提供估算方法和依据,且不对软件产品的销售价格做出任何规定,可以看作是行规。1. 软件开发价格估算方法软件开发价格与工作量、商务成本、国家税收和企业利润等项有关。为了便于计算,给出一个计算公式:软件开发价格 = 开发工作量 × 开发费用/人·月1.1 开发工作量软件开发工作量与估算工作量经验值、风险系数和复用系数等项有关。开发工作量 = 估算工作量经验值 × 风险系数 × 复用系数.

2021-07-16 16:37:50 3848

原创 Self Encapsulate Field(自封装字段)

动机在“字段访问方式”这个问题上,存在两种截然不同的观点:其中一派认为,在该变量定义所在的类中,你可以自由访问它:另一派认为,即使在这个类中你也应该只使用访问函数间接访问。两派之间的争论可以说是如火如荼。面临选择时,我总是做两手准备。通常情况下我会很乐意按照团队中其他人的意愿来做。就我自己而言,我比较喜欢先使用直接访问方式,直到这种方式给我带来麻烦为止,此时我就会转而使用间接访问方式。重构给了我改变主意的自由。做法为待封装字段建立取值/设值函数。找出该字段的所有引用点,将它们全部改为调用取值/设

2021-07-16 09:38:06 271

原创 Introduce Foreign Method(引入外加函数)

动机这种事情发生过太多次了:你正在使用一个类,它真的很好,为你提供了需要的所有服务。而后,你又需要一项新服务,这个类却无法供应。于是你开始咒骂:“为什么不能做这件事?”如果可以修改源码,你便可以自行添加一个新函数:如果不能,你就得在客户端编码,补充你要的那个函数。但是不要忘记:外加函数终归是权宜之计。如果有可能,你仍然应该将这些函数搬移到它们的理想家园。如果由于代码所有权的原因使你无法做这样的搬移,就把外加函数交给服务类的拥有者,请他帮你在服务类中实现这个函数。做法在客户类中建立一个函数,用来提供

2021-07-15 09:40:26 267

原创 Remove Middle Man(移除中间人)

动机在Hide Delegate的“动机”一节中,我谈到了“封装受托对象”的好处。但是这层封装也是要付出代价的,它的代价就是:每当客户要使用受托类的新特性时,你就必须在服务端添加一个简单委托函数。随着受托类的特性(功能)越来越多,这一过程会让你痛苦不已。服务类完全变成了一个“中间人”,此时你就应该让客户直接调用受托类。很难说什么程度的隐藏才是合适的,还好,有了Hide Delegate和Remove Middle Man,你大可不必操心这个问题,因为你可以在系统运行过程中不断进行调整。随着系统的变化,“

2021-07-14 20:49:02 362

原创 Hide Delegate(隐藏“委托关系”)

动机如果某个客户先通过服务对象的字段得到另一个对象,然后调用后者的函数,那么客户就必须知晓这一层委托关系。万一委托关系发生变化,客户也得相应变化。你可以在服务对象放置一个简单的委托函数,将委托关系隐藏起来,从而去除这种依赖。这么一来,即便将来发生委托关系上的变化,变化也将被限制在服务对象中,不会涉及客户。做法对于每一个委托关系中的函数,在服务对象端建立一个简单的委托函数。调整客户,令它只调用服务对象提供的函数(如果使用者和服务提供者不在同一个包,考虑修改委托函数的访问权限,让客户得以在包之外调用它

2021-07-14 15:28:07 413

原创 Inline Class(将类内敛化)

动机正好与Extract Class相反。如果一个类不再承担足够责任、不再有单独存在的理由(这通常时因为此前的重构动作移走了这个类的责任),我就会挑选这一“萎缩类”的最频繁用户(也是个类),以Inline Class手法将“萎缩类”塞进另一类中。做法在目标类身上声明源类的pulic协议,并将其中所有函数委托至源类(如果“以一个独立接口表示源类函数”更合适的话,就应该在内敛之前先使用Extract Interface)。修改所有源类引用点,改而引用目标类(将源类声明为private,以斩断包之外的所

2021-07-12 12:11:38 590

原创 Extract Class(提炼类)

动机你也许听过类似这样的教诲:一个类应该是一个清楚的抽象,处理一些明确的责任。但是在实际工作中,类会不断成长扩展。你会在这儿加入一些功能,在那儿加入一些数据。给某个类添加一项新责任时,你会觉得不值得为这项责任分离出一个单独的类。于是,随着责任不断增加,这个类会变得过分复杂。很快,你的类就会变成一团乱麻。做法决定如何分解类所负的责任。建立一个新类,用以表现从旧类中分离出来的责任。建立“从旧类访问新类”的连接关系(有可能需要一个双向连接。但是在真正需要它之前,不要建立“从新类通往旧类”的连接)。对

2021-07-12 08:55:43 503

原创 关于重构(Refactoring)

2021-07-11 21:08:49 2121

原创 Move Field(搬移字段)

动机在类之间移动状态和行为,是重构过程中必不可少的措施。随着系统的发展,你会发现自己需要新的类,并需要将现有的工作责任拖到新的类中。在这个星期看似合理而正确的设计决策,到了下个星期可能不再正确。这没问题。如果你从来没遇到这种情况,那才有问题。如果我发现对于一个字段,在其所驻类之外的另一个类中有更多函数使用了它,我就会考虑搬移这个字段。上述所谓“使用”可能是通过设值/取值函数间接进行的。我也可能移动该字段的用户(某个函数),这取决于是否需要保持接口不受变化。如果这些函数看上去很适合待在原地,我就选择搬移字

2021-07-10 10:26:07 378

原创 Move Method(搬移函数)

动机“搬移函数”是重构理论的支柱。如果一个类有太多行为,或如果一个类与另一个类有太多合作而形成高度耦合,我就会搬移函数。通过这样的手段,可以使系统中的类更简单,这些类最后也将更干净利落地实现系统交付的任务。做法检查源类中被源函数所使用的一切特性(包括字段和函数),考虑它们是否也该搬移(如果某个特性只被你打算搬移的那个函数用到,就应该将它一并搬移。如果另有其他函数使用了这个特性,你可以考虑将使用该特性的所有函数一起搬移。有时候,搬移一组函数比逐一搬移简单些)。检查源类的子类和超类,看看是否有该函数的

2021-07-09 18:05:33 1569

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除