库和框架有什么区别?

库的英语为Library(简写为Lib),框架的英语为Framework。

库主要是为了复用解决了某一个(某一类)问题的代码,将代码组织形成一个产品,供程序员下载、加入自己的项目。面向对象的代码组织形成的库也叫类库。面向过程的代码组织形成的库也叫函数库。在函数库中的可直接调用的函数叫库函数。

开发者在使用库的时候,一般只需使用库中的一部分类或函数,解决自己的某个问题,实现自己的功能。

框架则主要为了解决某个较大领域里的多个问题而开发的产品。框架用户一般只需要使用框架提供的类或函数,即可实现全部功能。可以说,框架是库的升级版,一个框架由多个库组成。

开发者在使用框架的时候,必须使用这个框架的全部代码。

以前和一些老程序员讨论,到底什么是framework,什么是library,为啥都说Spring是framework,jackson是library?结论是你得把代码交给framework管理,但是却可以自由的使用library。有一定编程经验的人,有时候会觉得framework限制了自己的表达能力,从而倾向于自己写library给自己用。

所谓:you call library,framework calls you。

假如我们要买一台电脑。框架为我们提供了已经装好的电脑,我们只要买回来就能用,但你必须把整个电脑买回来。这样用户自然轻松许多,但会导致很多人用一样的电脑,或你想自定义某个部件将需要修改这个框架。而库就如自己组装的电脑。不同的库为我们提供了不同的部件,我们需要自己组装电脑,如果某个部件库未提供,我们也可以自己做。库在开发小程序时使用起来非常灵活,但开发大型程序时,使用框架会更加方便。

参考

https://www.zhihu.com/question/521822847/answer/3141874937

https://www.freecodecamp.org/news/the-difference-between-a-framework-and-a-library-bd133054023f/

https://stackoverflow.com/questions/148747/what-is-the-difference-between-a-framework-and-a-library

模块、组件和服务分别是什么?它们有什么区别?

组件也叫构件。什么是组件?一个组件就是一个可以独立更换和升级的软件单元。组件具有如下特点:
1 能实现一定功能,或者提供一些服务。
2 不能单独运行,要作为系统的一部分来发挥作用。
3 是物理上的概念,不是逻辑上的概念。
4 可单独维护、可独立升级、可替换而不影响整个系统。
组件是物理上独立的一个东西,它可单独维护、升级、替换,画构件图的目的就是要做系统的构件设计,思考系统在物理上的划分,可利用现有哪些构件,哪些部分可做成构件供以后的项目重用等。

问题1:我们做软件设计时, 往往会提到 “模块 “ 这一词,“模块” 是不是构件呢?
不一定,每个人心中的“模块”的标准是不太一样的,有时候会按业务逻辑来划分模块,有时候从技术的角度来划分。模块只是为了方便说明问题,将软件人为地划分为几个部分而已,我们可以对照组件的上述几个特点来判断 “模块” 是不是构件。

问题2:软件常常会采用分层设计,那一层是一个构件吗?
大部分情况下分层设计中的每一层,仅是一个逻辑上的划分,物理上并不是单独的文件,这时这些分层不是组件。但具体要看实际的设计情况,可对照组件的上述几个特点来判断。

问题3:如何区分“服务”(service)和“组件”(component)?
所谓“组件”是指这样一个软件单元:它将被作者无法控制的其他应用程序使用,但后者不能对组件进行修改。也就是说,使用一个组件的应用程序不能修改组件的源代码,但可以通过作者预留的某种途径对其进行扩展,以改变组件的行为。

服务和组件有某种相似之处:它们都将被外部的应用程序使用。在我看来,两者之间最大的差异在于:组件是在本地使用的软件库(例如JAR文件、程序集、DLL、或者源码导入);而服务是进程外的组件,通过同步或异步的本机进程之间通信或远程接口调用(例如web service、消息系统、RPC,或者socket)这样的机制来被应用程序使用。

服务也可以调用其他服务,因为服务本身也是一个应用程序。

可以把一个个服务映射为一个个运行时的进程,但这仅仅是一个近似。一个服务也可以包括多个进程,比如一个服务应用程序的进程和仅被该服务使用的数据库进程。

服务可被独立部署。如果一个应用系统由在单个进程中的多个软件库所组成,那么对任一组件做一处修改,都不得不重新部署整个应用系统。但是如果该应用系统被分解为多个服务,那么对于一个服务的多处修改,仅需要重新部署这一个服务,例外是更改服务暴露出来的接口。

以服务的方式来实现组件化的另一个结果是,能获得更加显式的(explicit)组件接口。

服务的远程调用,比起进程内调用,远程调用更加昂贵。

参考
《微服务》 Martin Fowler
《IoC容器和依赖注入模式》 Martin Fowler
《火球 UML大战需求分析》

复杂性守恒定律 (The Law of Conservation of Complexity or Tesler’s Law)

复杂性守恒定律 (The Law of Conservation of Complexity or Tesler’s Law):系统中存在着一定程度的复杂性,并且不能减少。

系统中的某些复杂性是无意的。这是由于结构不良,错误或者糟糕的建模造成的。这种无意的复杂性可以减少或者消除。然而,由于待解决问题有固有的复杂性,这些复杂性是内在的。这些复杂性可以转移,但不能消除。

该定律有趣的一点是,即使简化整个系统,内在的复杂性也不会降低。它会转移给用户,并且用户必须以更复杂的方式行事。

现实世界的复杂度无法使用代码来消除,如果你想少写代码,就要多写配置;如果你想少写配置,就要多写注解……

业务逻辑无法使用代码来化简或消除,业务逻辑不写在代码里,那就一定会转移到配置文件里或者其他什么地方。

业务逻辑不是程序员能控制的,程序员只负责代码实现,公司的领导层或许可以通过流程再造来改变业务逻辑。

因为现实世界的复杂性无法在代码层面消除,过度地抽象、解耦、套用设计模式反而会增加代码的复杂度。

关于配置文件

配置文件尽量保持简单直白,不要有分支或循环逻辑。分支或循环逻辑应该放到控制器里,因为控制器就是写业务逻辑代码的,改需求改的是控制器里代码,不变化的代码封装在模型里。配置文件里的配置信息应该是控制器的辅助,而不是相反。

由于外部环境的改变而经常跟着改变的变量值应该写在配置文件里,例如数据库配置信息测试环境一套,生产环境另一套,系统环境变量,要启用的进程数、线程数,公司名称、学校名称等,而不要把业务逻辑中的流程控制语句写在配置文件里。

总之,不要过度设计,不要过早优化,等版本稳定下来了再用设计模式重构代码也不迟。当然如果你的项目不缺钱也不缺时间,那么过早优化完全没有问题。

参考

https://github.com/nusr/hacker-laws-zh

https://en.wikipedia.org/wiki/Law_of_conservation_of_complexity

https://ferd.ca/complexity-has-to-live-somewhere.html

https://www.zhihu.com/question/429538225

沃斯定律(Wirth’s Law):软件比硬件更容易变慢

因为软件可不遵循摩尔定律!这也是说明了,当把钱花在硬件上不再能获得线性收益时,就应该招几个大牛程序员(专家)了,把钱花在大牛程序员上,企求带来超线性的收益。

另请参见安达尔定律(Amdahl’s Law)和古斯塔夫森定律(Gustafson’s Law)。