瑞士军刀 VS 单一职责原则

2024-03-15 04:10

本文主要是介绍瑞士军刀 VS 单一职责原则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://www.cnblogs.com/ldp615/archive/2009/08/28/1555952.html

 

“单一职责原则”是面向对象软件开发的基本原则之一,面向对象的思想又是从现实世界中总结出来。可最近发现面向对象的单一职责原则与现实好似有些冲突。

 我们先看下引起事非争端的优雅的瑞士军刀吧:

  

 瑞士军刀都是多功能工具刀,上面左图的至少有14项功能,右图的至少有34项功能!

 

 

 这个是带MP3播放功能的!还有更加强大的:
        

 这是知名瑞士刀制造商,威戈(Wenger)最新推出了一把长8.75英寸、重2磅(1公斤)内含87种工具的瑞士刀,编号16999。看来几乎曾经出现在瑞士刀里头的东西都有了,它包括七种不同的小刀、高尔夫球鞋清理钳、脚踏车链铆钉调整器,还有一只测距达300英尺(90公尺)的雷射笔。这把瑞士刀的作用,可能是让一个当打完高尔夫球的人,能够在清理完自己的球鞋以后,马上把脚踏车给调校好,接着骑到一个人烟罕至的树林里。

 这个是相当“变态”的,我最近一直在写扩展方法的文章,所有文章中的扩展方法合在一起也和军刀有点类似了。

 瑞士军刀和普通的刀(单一职责设计的刀)最大的不同就是方便(先不考虑最后一个,哈哈),它是多功能刀,而不是简简单单的刀。从功能上看,瑞士军刀“打破”了单一职责原则。也许产品的设计和软件系统的设计不能相提并论,毕竟归规模、复杂度相差太远。单一职责原则是为解决复杂问题而制定的。那我们就换个思路去考虑,我们构建一支军队,现在要给士兵配一些装备。军队、士兵、装备全是对象!有点类似了吧。我们是给士兵配一把多功能的瑞士军刀,还是配很多很多零散的小工具呢? 

 以上的对比可能不恰当,但从中可推出一个结论:有时使用单一职责,没看到好的效果,反而更麻烦。

 先来看下单一职责原则(Single-Responsibility Principle)的定义,Robert C. Martin对它的解释是:Each class should have one and only one reason to change. 单一职责并不是直观理解为类只能有单一的功能,单一职责是从变化的角度去考虑的。一个类应该(注意是should而不是must,是应该而不是必须)有且只有一个因起它变化的原因(直译)。

 Martin的解释改变的单一职责原则的含义:

 1.“单一职责”不是指具有单一功能(而是只因一个原因变化);

 2.“原则”更像是一种比较强烈的建议。


 基于这两点理解,引发出我的观点:

 1.对象颗粒大小不同,对小颗粒对象应用单一职责是不合适的:小颗粒对象如小公司的员工,需要一人兼数职。如果应用单一职责,小颗粒对象又将分解成更多更小颗粒的对象,数量越来越多,给我们命名、使用、维护带来麻烦。

 2.基础类库不适合:比如字符串常用处理的类,取子字符串、转换为其它类型、为空判断,放在一个类中反而使用更方便!

 3.“单一职责原则”更适于中大型系统,系统越小使用该原则越不划算:一超个小系统就一个界面,面象对象都不必使用。

 4.单一职责当然要用,但不是用到每个细节:一些局部不用对整体影响很小,反而更灵活、更省时间。 

 4.原则是前辈能多年的经验总结出来的,原则的名字可能不变,但原则的内含可能在悄悄变化。

 5.“principle”、“原则”有可能是前人一种表达强烈建议的方式,而不是“must”、“必须”。

 

 再回头看前面的军刀,它有多种功能,但能引起它变化的原因是什么呢?这里想到一个,客户应用。根据客户的具体应用,会有多种功能组合,不同组合又分成不同系列...客户有了新的需求,就会推出新产品...这个过程中可能包含了对象的继承、组合等等,应该很复杂。当然也遇到客户需求相当相当不一般,所以推出前面很变态的那款,应该算个特例吧!

 再考虑:军刀上有一个开啤酒瓶用的启子,如果啤酒瓶的盖子大小变了呢?带MP3功能的军刀上有耳机插孔,耳机接口变了怎么办?仔细想想,能引起它变化的原因还真不少。但这些变化发生的可能性太小了,即便是真的发生了,军刀该退役了,新品就推出了。 

 所以,我认为瑞士军刀还是比较符合单一职责原则的!前面推出的结论“有时使用单一职责,没看到好的效果,反而更麻烦”,有两种解释: 

 1.将单一职责错误理解成了单一功能,又进一步去分解功能,所以麻烦;

 2.不分对象大小,不看程序规模,统统使用:用的不恰当,所以麻烦。 


 最后结论,面向对象的思想与原则与现实世界是一致的,并且与时俱进。

 本人没有受过正规的软件教育,对面向对象理解也是残缺不全,对技术也是东一块西一块,杂乱的想法也很多。说的不对请各位前辈指正!

-------------------

思想火花,照亮世界

分类: c#
标签: 面向对象, 单一职责
绿色通道: 好文要顶 关注我 收藏该文 与我联系
鹤冲天
关注 - 14
粉丝 - 224
荣誉: 推荐博客
+加关注
2
0
(请您对文章做出评价)
« 博主前一篇: c# 扩展方法奇思妙用变态篇四:string 的翻身革命
» 博主后一篇: c# 扩展方法奇思妙用高级篇四:对扩展进行分组管理
Add your comment

35 条回复

  1. #1楼 资深那一年[未注册用户]2009-08-28 19:25
    先抢个沙发再评论
  2. #2楼 资深那一年[未注册用户]2009-08-28 19:39
    先说一下瑞士军刀它到底是什么?是工具!所以如果要是一个工具类做成“瑞士军刀”是没问题的。因为引起他变化的原因少,相对稳定。(当然功能也要限量 向第三幅图的就不好了)OO 最根本的是要干什么?是要封装变化,哪里有可能出现变化就封装哪里。所以个人认为单一原则 和 军刀 基本是两回事。
  3. #3楼 丁丁      2009-08-28 19:48
    瑞刀三层的最实用,四层的已经太厚,对于特定用途,一层瑞刀的也没啥不好。所以,看方便啦,写代码也一样
  4. #4楼 Todd Wei      2009-08-28 20:09
    楼主选题很有启发性,能引发人的思考本身就很不错。
  5. #5楼 金色海洋(jyk)      2009-08-28 21:02
    我觉得用瑞士军刀举例子不大恰当。

    瑞士军刀只不过是若干“单一职责的刀”的组合,只不过这种组合比较紧密。

    ============

    其实就是一句话:要分成小份,但是又不能太细。
  6. #6楼 zwws[未注册用户]2009-08-28 21:05
    引起瑞士军刀变化的原因只用一个,那就是功能的增加。军刀本身做为一个个体,和它实际应用的环境是非耦合的,所以我觉得不应该和单一职责放在一起谈,性质不同。

    比较赞同的说法是,单一职责的应该应用在粒度较大的点上,控制不好反而增加系统的复杂程度,得不偿失。
  7. #7楼 Ivony...      2009-08-28 21:46
    其实怎么说呢,有句古话说的不错,尽信书不如无书,很多东西不能从字面上去理解,不过这倒不是什么大事,某些大牛也经常闹出这种事情。就像前阵子我特意撰文反驳的什么“类型要高内聚低耦合”。

    其实“单一职责原则”这个名字非常容易让人误解,而对它的解释“只应有一个引起变化的原因”又显得比较深奥,所以很多人是知其然不知其所以然。

    事实上单一职责与粒度没有关系。简单的说,.NET Framework有一个类型,SqlConnection,这个类型是负责建立和维护数据库连接的,显然其设计是符合单一职责原则的。我们现在假设自己做了一个类型,这个类型不但负责打开和维护数据库连接,还要负责创建命令,执行查询,并包装输出结果等等一系列事情。但这个类并不是就违背了单一职责原则,它还是单一职责的,他负责与数据库的交互。如果我们要对数据库进行任何更改,需要修改这个类型的实现,但与数据库无关的更改,就不需要更改它了。在这样的例子里,显然后者的设计粒度比前者大得多。

    那么什么是违背单一职责的呢,比如说一个类型除了与数据库交互,还要负责到前面去收集表单数据,这个时候我们就可以认为这里面有职责不明的问题,因为至少有两个引起它修改的原因,UI的变更或者数据库的变更。
  8. #8楼 行万里路      2009-08-29 00:40
    如果从面向对象的角度去分析瑞士军刀, 其并不是见得是一个好的设计。导致它变化因素太多(可用功能、是否便于携带、是否可以随意拆卸等)。但是为什么它在市场仍如此受到青睐,这其中可能还有其他原因。如品牌、本身多功能就是它卖点。
    如果让我设计,我可能会把军刀的Body设计成一个接口容器(就像.NET Windows Form模型中的IServiceContainer),而军刀上那些功能我可能会将它们做容器中的服务提供者(ServiceProvider),他们实现了IServiceProvider这样一个接口。只有实现了这个接口的功能才可以装上军刀。大家可能知道了,他其实就是一个可拆卸、可插拔的多功能道具。
    (愚见)
  9. #9楼 飞林沙      2009-08-29 02:45
    其实我绝对单一职责究竟多单一,要看整个系统需求分析时所划分的对象粒度而定。
    还是那句话,满足需求的设计就是好设计。
  10. #10楼 Nick Wang (懒人王)      2009-08-29 04:52
    “只因一个原因变化”这个确实很晦涩,可以从另一个角度衡量,如果在两个意图不同的功能中都是用了一个类,而这个类的某些方法只在其中一个功能中使用,那么可以说它不是职责单一的。但是意图是否相同,取决于你自己对它的划分,粒度可能很粗,也可能很细。

    1.对象颗粒大小不同,对小颗粒对象应用单一职责是不合适的:小颗粒对象如小公司的员工,需要一人兼数职。如果应用单一职责,小颗粒对象又将分解成更多更小颗粒的对象,数量越来越多,给我们命名、使用、维护带来麻烦。

    --这个不认同,越小的对象越容易和应该职责单一,如果你所谓的小颗粒对象指的是功能(方法)较少或代码行数较少的类。

    2.基础类库不适合:比如字符串常用处理的类,取子字符串、转换为其它类型、为空判断,放在一个类中反而使用更方便!
    --字符串的例子正好是职责单一啊,因为它只管字符串,不管其它类型。

    3.“单一职责原则”更适于中大型系统,系统越小使用该原则越不划算:一超个小系统就一个界面,面象对象都不必使用。
    --跟系统规模大小无关,跟程序的寿命有关。一个程序写出来不管规模大小,如果要生存多年,维护就是主要工作,系统设计的好坏直接决定维护成本。

    4.单一职责当然要用,但不是用到每个细节:一些局部不用对整体影响很小,反而更灵活、更省时间。
    --一个系统的设计思路不统一,怎么让人理解和维护,今天的灵活和省时间,变成明天的难以维护和费时间。

  11. #11楼[楼主] 鹤冲天      2009-08-29 08:24
    引用资深那一年:如果要是一个工具类做成“瑞士军刀”是没问题的。因为引起他变化的原因少,相对稳定。(当然功能也要限量 向第三幅图的就不好了)

    同意 资深那一年 的观点!
  12. #12楼[楼主] 鹤冲天      2009-08-29 08:26
    引用金色海洋(jyk):其实就是一句话:要分成小份,但是又不能太细。
    同意,这是对“单一职责原则”最简单、最通俗的理解!
  13. #13楼[楼主] 鹤冲天      2009-08-29 08:34
    引用Ivony...:简单的说,.NET Framework有一个类型,SqlConnection,这个类型是负责建立和维护数据库连接的,显然其设计是符合单一职责原则的。我们现在假设自己做了一个类型,这个类型不但负责打开和维护数据库连接,还要负责创建命令,执行查询,并包装输出结果等等一系列事情。但这个类并不是就违背了单一职责原则,它还是单一职责的,他负责与数据库的交互。

    Ivony...的思想值得去好好思考!
  14. #14楼[楼主] 鹤冲天      2009-08-29 08:36
    引用行万里路:如果让我设计,我可能会把军刀的Body设计成一个接口容器(就像.NET Windows Form模型中的IServiceContainer),而军刀上那些功能我可能会将它们做容器中的服务提供者(ServiceProvider),他们实现了IServiceProvider这样一个接口。只有实现了这个接口的功能才可以装上军刀。大家可能知道了,他其实就是一个可拆卸、可插拔的多功能道具。

    想法很独到!也期待有这种设计的军刀出现!
  15. #15楼[楼主] 鹤冲天      2009-08-29 08:51
    引用Nick Wang (懒人王):
    1.对象颗粒大小不同,对小颗粒对象应用单一职责是不合适的...
    --这个不认同,越小的对象越容易和应该职责单一,如果你所谓的小颗粒对象指的是功能(方法)较少或代码行数较少的类。
    ...

    功能(方法)少或代码行数少的类,如果功能相近,不如合成一个工具类,就像我们把很多小工具放入工具箱中一样。也和瑞士军刀差不多,它集合了多个单一职责的小工具。

    引用Nick Wang (懒人王):2.基础类库不适合:比如字符串...
    --字符串的例子正好是职责单一啊,因为它只管字符串,不管其它类型。

    我最近一直在写扩展方法的相关文章,通过扩展,我赋予string很多功能,如IsMatch(正则判断)、ToInt/ToDateTime(转换为其它类型)、ExecuteDOS/ExecuteSQL(执行DOS命令或SQL语句)。扩展后的string职责多了很多,这些扩展是否也单一职责呢?

    引用Nick Wang (懒人王):3.“单一职责原则”更适于中大型系统,系统越小使用该原则越不划算...
    --跟系统规模大小无关,跟程序的寿命有关。一个程序写出来不管规模大小,如果要生存多年,维护就是主要工作,系统设计的好坏直接决定维护成本。

    我感觉系统越小越稳定,系统越小引起它变化的原因也越少。超小系统维护不是问题,大不了重写一个。感觉超小系统中还要运行各种原则,是一种极端主义。

    引用Nick Wang (懒人王):单一职责当然要用,但不是用到每个细节...
    --一个系统的设计思路不统一,怎么让人理解和维护,今天的灵活和省时间,变成明天的难以维护和费时间。

    系统设计的思路应该是整体上的,一个类的设计应该侧重接口或公有成员部分,至于内部实现则可以相对灵活一点。
  16. #16楼 heros      2009-08-29 08:57
    瑞士军刀方便吗,我并不觉得。也许我的系统中只需要一个指甲刀,但我不得不带上一堆我用不着的元素。如果这一堆元素的数量并不大时,也许我可以忍受,但数量庞大时…………,就像最后那一把军刀一样,要我说就是垃圾一推。功能设计应该尽量的细粒度,必要的时候可以组合。行万里路的想法很不错,对外提供稳定的接口,内部功能可以灵活变换。正如strategy、facade等的意图一样。
  17. #17楼[楼主] 鹤冲天      2009-08-29 09:06
    引用heros:瑞士军刀方便吗,我并不觉得。也许我的系统中只需要一个指甲刀,但我不得不带上一堆我用不着的元素。如果这一堆元素的数量并不大时,也许我可以忍受,但数量庞大时…………,就像最后那一把军刀一样,要我说就是垃圾一推。

    产品设计考虑特定的用户需求,你只需要一个指甲刀,去买指甲刀好了,还便宜,重点是适用!最后一把军刀我也很难接受,但存在就有道理,肯定有人喜欢这样,也许是为了收藏!

    引用heros:对外提供稳定的接口,内部功能可以灵活变换。正如strategy、facade等的意图一样

    我也赞同这个!
  18. #18楼 heros      2009-08-29 09:14
    产品可以包含n多的功能,但设计时要考虑细粒度。而不是在设计时就打造一个上帝。也许我的系统中只需要一个指甲刀,可能一会又需要一个小锉刀,需要指甲刀我给你一个指甲刀,需要小锉刀我给你一个小小锉刀,而不是一下扔一个瑞士军刀,“喂,都在这,自己挑吧。”
    存在就有道理,但存在不是就正确。
  19. #19楼[楼主] 鹤冲天      2009-08-29 09:31
    @heros
    产品有n多功能,也会样n多种型号,也会有n多种样式,也会有n多公司生产...作为消费者我们选择的余地非常多的!
    我现在有点感觉.Net Framwork就像是一个庞大的“军刀”,里面类异常多,类中的方法也很多,我们能用到的又能有多少,不还是从里面挑吗?
    产品可多样化,但Framwork要考虑通用性,能满足绝大多数人的需要。
  20. #20楼 heros      2009-08-29 09:35
    引用鹤冲天:
    @heros
    产品有n多功能,也会样n多种型号,也会有n多种样式,也会有n多公司生产...作为消费者我们选择的余地非常多的!
    我现在有点感觉.Net Framwork就像是一个庞大的“军刀”,里面类异常多,类中的方法也很多,我们能用到的又能有多少,不还是从里面挑吗?
    产品可多样化,但Framwork要考虑通用性,能满足绝大多数人的需要。

    对不起,我们现在讨论的是Simple Response Principle。n多的类不在讨论范围。
  21. #21楼 韦恩卑鄙      2009-08-29 09:54
    单一职责 在我来说 更像是对接口进行细分的标准

    比如

    IPerson 吃饭说话听话微笑
    {eat() say () listen () smile() }

    IMale 站着尿尿 玩女人
    {StandingPee() , FuxkChicken()}

    而我实现了 Wayne :IPerson,IMale

    在我想要 FuxkChicken的时候 我不要
    Wayne.FuxkChicken()
    因为方法太多了 我找不到
    我宁可
    ((IMail)Wayne).FuxkChicken() 点起来比较好找(当然我一般参数类型就是 IMale 所以也不会拆箱)

    这也是我建议你扩展方法分组的原因

    换个角度说 你图中瑞士军刀变态 但是真的是无顺序存放的么?它仍然是多个功能分组,分别实现的,设计师那能那么不负责

    所以我强调只要按照单一职责原则进行分组 那么大家也会欣然接受你的扩展实现
  22. #22楼[楼主] 鹤冲天      2009-08-29 10:12
    @韦恩卑鄙
    韦恩兄言语不羁,很豪放!
    IPerson、IMale让我有种恍然大悟的感觉!
    对扩展进行分组的想法也在逐步形成中!
  23. #23楼[楼主] 鹤冲天      2009-08-29 10:16
    引用韦恩卑鄙:((IMale)Wayne).StandingPee()

    Wayne.As<IMale>.StandingPee()
    哈哈,我又多个一个思路:增加一个As<T>扩展,所有的扩展都扩展在T上,韦恩兄感觉如何?
    T最好是接口,再者As以A打头,比较靠前,容易找也容易与其它的区分!
  24. #24楼 乐蜂网[未注册用户]2009-08-29 10:38
    写的很好!
  25. #25楼 Nick Wang (懒人王)      2009-08-29 11:33
    @鹤冲天
    1. 工具类本身的职责就是单一的啊,不过也可以细分成不同方面的工具,即使一个工具类有20多个方法,它也可能是SRP的。但如果其中包含了数据库、字符串、html等等的功能,也可以说不是SRP的。
    2. 对字符串的扩展也还是字符串操作,当然也是SRP的。但是如果扩展中有针对数据库的、针对测试的等等,还是分成多个扩展类比较清晰。
    --窃以为工具类并不是OO的一部分,SRP与否也并不是太大的问题,主要还是从清晰和可读性上考虑。

    3.这要看你如何定义系统的大小了。如果以功能来看,twitter的功能也很单一啊,但是并不意味着就不需要维护,不会有很长的生命周期。

    4.外部接口就像是穿的外衣,是给别人看的;内部实现就像内衣,舒服不舒服自己知道。而且外部接口一般是不能改变的或甚少改变的,内部实现则是会因为很多原因而改变,所以内部实现也是很重要的。
  26. #26楼 陶发辉      2009-08-29 11:50
    瑞士军刀=管理(组合(单一职责刀*N))
    但是它的前题是:
    1.每个刀都质量非常好,基本不会坏
    2.有足够的空间
    3.有足够的钱
    程序同理。
  27. #27楼 韦恩卑鄙      2009-08-29 12:44
    引用鹤冲天:
    引用韦恩卑鄙:((IMale)Wayne).StandingPee()

    Wayne.As<IMale>.StandingPee()
    哈哈,我又多个一个思路:增加一个As<T>扩展,所有的扩展都扩展在T上,韦恩兄感觉如何?
    T最好是接口,再者As以A打头,比较靠前,容易找也容易与其它的区分!

    这个方法我很喜欢 搞得我也想试验下了
  28. #28楼[楼主] 鹤冲天      2009-08-29 13:38
    引用Nick Wang (懒人王):窃以为工具类并不是OO的一部分,SRP与否也并不是太大的问题,主要还是从清晰和可读性上考虑。

    这个观点(对我)很新颖!支持!
  29. #29楼 Sojin      2009-08-29 14:24
    我觉得某个东西是否符合某个原则要看你是怎么去设计和理解这个东西。

    某种瑞士军刀如果不可灵活拆卸某个小工具,那他只能看成一个整体,当然就不符合,如果某种瑞士军刀是可以拆卸的,就可以将军刀看成容器,他的职责就是组合这些工具。这样军刀类并不需要知道具体的工具,添加和减少工具也不会引起他结构的变化。

    在现实中可能虽然可拆卸的灵活,但成本更贵,用户就会按自己的需求去购买东西,都会有他的市场。
    对应设计中有时候设计的成本高,又绝对没有这种变化的需要,不符合某个职责又有什么所谓呢。



  30. #30楼 Todd Wei      2009-08-29 15:22
    SRP指的是组件职责单一,瑞士军刀不是组件,而是系统。没有谁说系统要职责单一的,比如一套ERP系统,又是生产,又是财务,又是客户,什么都有。放到瑞士军刀的例子里面,瑞士军刀系统是由多个xxx刀组件构成的,每个xxx刀的职责单一,这是SRP。系统功能多样化和组件职责单一化并不矛盾。

    其实,所谓职责或功能是有抽象层次的,高层次的功能包含了若干低层次的功能。系统对应高的抽象层次,也可以认为它是功能单一,比如:ERP系统,它唯一的功能就是企业资源计划,不是搜索引擎。谈论SRP应该放在对象所处的层次上。
  31. #31楼 heros      2009-08-29 17:31
    引用Todd Wei:

    "谈论SRP应该放在对象所处的层次上"。上面我说的那么多,也没这句表达的清楚。SRP不能针对整个OA系统,它应该在设计员工类时被使用。
  32. #32楼 麒麟.NET      2009-08-29 22:42
    瑞士军刀是一个产品,不是一个类,产品的功能自然会很多,而我们看到的是一个集合了多种功能的产品,功能多,职责复杂,也就不足为怪了
  33. #33楼 轩辕健      2009-08-29 22:44
    我觉得,瑞士军刀本身就已经是一个集成的系统,它并不是一个单一的整体对象。其组成就是由更多更小的功能实现体组合而成。
  34. #34楼 take it and go      2011-04-29 13:25
    瑞士军刀其实有些功能对我们多余了
  35. #35楼[楼主] 鹤冲天      2011-05-22 17:28
    @take it and go
    呵呵,是的

这篇关于瑞士军刀 VS 单一职责原则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810750

相关文章

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少

PHP最长单一子串

<?php//方法一$s='abcccddddddcdefg';$max='';while($s!=''){$i=0; while($i<strlen($s) && $s[$i]==$s[0]) $i++;if ($i>strlen($max)){$max=substr($s,0,$i);} $s=substr($s,$i);}echo $m

VS Code 调试go程序的相关配置说明

用 VS code 调试Go程序需要在.vscode/launch.json文件中增加如下配置:  // launch.json{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information,

探索Invoke:Python自动化任务的瑞士军刀

文章目录 探索Invoke:Python自动化任务的瑞士军刀背景:为何选择Invoke?`invoke`是什么?如何安装`invoke`?简单的`invoke`库函数使用方法场景应用:`invoke`在实际项目中的使用场景一:自动化测试场景二:代码格式化场景三:部署应用 常见问题与解决方案问题一:命令执行失败问题二:权限不足问题三:并发执行问题 总结 探索Invoke:P

水处理过滤器运行特性及选择原则浅谈

过滤属于流体的净化过程中不可缺的处理环节,主要用于去除流体中的颗粒物或其他悬浮物。水处理过滤器的原理是利用有孔介质,从流体中去除污染物,使流体达到所需的洁净度水平。         水处理过滤器的滤壁是有一定厚度的,也就是说过滤器材具有深度,以“弯曲通 道”的形式对去除污染物起到了辅助作用。过滤器是除去液体中少量固体颗粒的设备,当流体进入置有一定规格滤网的滤筒后,其杂质被阻挡,而

解决服务器VS Code中Jupyter突然崩溃的问题

问题 本来在服务器Anaconda的Python环境里装其他的包,装完了想在Jupyter里写代码验证一下有没有装好,一运行发现Jupyter崩溃了!?报错如下所示 Failed to start the Kernel. ImportError: /home/hujh/anaconda3/envs/mia/lib/python3.12/lib-dynload/_sqlite3.cpython-

设计模式 -- 职责链模式(Chain of Responsibility Pattern)

1 问题引出 1.1 学校 OA 系统的采购审批项目 如果金额 小于等于 5000, 由教学主任审批 (0<=x<=5000)如果金额 小于等于 10000, 由院长审批 (5000<x<=10000)如果金额 小于等于 30000, 由副校长审批 (10000<x<=30000)如果金额 超过 30000 以上,有校长审批 ( 30000<x) 1.2 传统方式 传统方式是

VSC++: 括号对称比较

括号的使用规则:大括号,中括号,小括号{[()]};中括号,小括号[()];小括号();大括号、中括号、小括号、中括号、小括号、大括号{[()][()]};大括号,中括号,小括号,小括号{[(())]};大括号,中括号,小括号,小括号{[()()]};小括号不能嵌套,小括号可连续使用。 {[]}、{()}、([])、({})、[{}]、{}、[]、{[}]、[(])都属非法。 char aa[

Apache Kylin VS Apache Doris全方位对比

1 系统架构 1.1 What is Kylin1.2 What is Doris2 数据模型 2.1 Kylin的聚合模型2.2 Doris的聚合模型2.3 Kylin Cuboid VS Doris RollUp2.4 Doris的明细模型3 存储引擎4 数据导入5 查询6 精确去重7 元数据8 高性能9 高可用10 可维护性 10.1 部署10.2 运维10.3 客服11 易用性 11.1