技术进阶

本贴最后更新于 2337 天前,其中的信息可能已经事过境迁

前言

程序员的编程技能随着经验的积累,会逐步提高。我认为编程能力可以分为一些层次。

下面通过两个维度展开编程能力层次模型的讨论。

一个维度是编程技能层次,另一个维度是领域知识层次。

编程技能层次

编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本。

0 段—非程序员:

初学编程者,遇到问题,完全是懵懵懂懂,不知道该怎么编程解决问题。也就是说,还是门外汉,还不能称之为“程序员”。计算机在他面前还是一个神秘的黑匣子。

1 段—基础程序员:

学习过一段时间编程后,接到任务,可以编写程序完成任务。

编写出来的代码,正常情况下是能够工作的,但在实际运行中,碰到一些特殊条件就会出现各类 BUG。也就是说,具备了开发 Demo 软件的能力,但开发的软件真正交付给客户使用,恐怕会被客户骂死。

程序员程序是写好了,但到底为什么它有时能正常工作,有时又不行,程序员自己也不知道。

运行中遇到了 bug,或者需求改变,需要修改代码或者添加代码,很快程序就变得结构混乱,代码膨胀,bug 丛生。很快,就连最初的开发者自己也不愿意接手维护这个程序了。

2 段—数据结构:

经过一段时间的编程实践后,程序员会认识到“数据结构 算法=程序”这一古训的含义。他们会使用算法来解决问题。进而,他们会认识到,算法本质上是依附于数据结构的,好的数据结构一旦设计出来,那么好的算法也会应运而生。

设计错误的数据结构,不可能生长出好的算法。

记得某一位外国先贤曾经说过:“给我看你的数据结构!”

3 段—面向对象:

再之后,程序员就会领略面向对象程序设计的强大威力。大多数现代编程语言都是支持面向对象的。但并不是说,你使用面向对象编程语言编程,你用上了类,甚至继承了类,你就是在写面向对象的代码了。

我曾经见过很多用 Java,Python,Ruby 写的面向过程的代码。

只有你掌握了接口,掌握了多态,掌握了类和类,对象和对象之间的关系,你才真正掌握了面向对象编程技术。

就算你用的是传统的不支持面向对象的编程语言,只要你心中有“对象”,你依然可以开发出面向对象的程序。

如,我用 C 语言编程的时候,会有意识的使用面向对象的技巧来编写和设计程序。用 struct 来模拟类,把同一类概念的函数放在一起模拟类。如果你怀疑用 C 语言是否能编写出面向对象的代码,你可以看一下 Linux 内核,它是用 C 语言编写的,但你也可以看到它的源代码字里行间散发出的浓浓的“对象”的味道。

真正掌握面向对象编程技术并不容易。

在我的技术生涯中,有两个坎让我最感头疼。

一个坎是 Dos 向 Windows 开发的变迁过程中,框架的概念,很长一段时间我都理解不了。Dos 时代,都是对函数库的调用,你的程序主动调用函数。Windows 时代,则换成了框架。就算是你的 main 程序,其实也是被框架调用的。UI 线程会从操作系统获取消息,然后发送给你的程序来处理。Java 程序员熟悉的 Spring 框架,也是这样一个反向调用的框架。

现在因为“框架”这个术语显得很高大上,因此很多“类库”/“函数库”都自称为“框架”。在我看来这都是名称的滥用。

“类库”/“函数库”就是我写的代码调用它们。

“框架”就是我注册回调函数到框架,框架来调用我写的函数。

另一个坎就是面向对象。很长一段时间我都不知道应该怎么设计类和类之间的关系,不能很好的设计出类层次结构来。

我记得当时看到一本外国大牛的书,他讲了一个很简单、很实用的面向对象设计技巧:“叙述问题。然后把其中的名词找出来,用来构建类。把其中的动词找出来,用来构建类的方法”。虽然这个技巧挺管用的,但也太草根了点,没有理论依据,也不严谨。如果问题叙述的不好,那么获得的类系统就会是有问题的。

掌握面向对象思想的途径应该有很多种,我是从关系数据库中获得了灵感来理解和掌握面向对象设计思想的。

在我看来,关系数据库的表,其实就是一个类,每一行记录就是一个类的实例,也就是对象。表之间的关系,就是类之间的关系。O-Rmapping 技术(如 Hibernate),用于从面向对象代码到数据库表之间的映射,这也说明了类和表确实是逻辑上等价的。

既然数据库设计和类设计是等价的,那么要设计面向对象系统,只需要使用关系数据库的设计技巧即可。

关系数据库表结构设计是很简单的:

1、识别表和表之间的关系,也就是类和类之间的关系。是一对一,一对多,多对一,还是多对多。这就是类之间的关系。

2、识别表的字段。一个对象当然有无数多的属性(如,人:身高,体重,性别,年龄,姓名,身份证号,驾驶证号,银行卡号,护照号,港澳通行证号,工号,病史,婚史 etc),我们写程序需要记录的只是我们关心的属性。这些关心的属性,就是表的字段,也就是类的属性。“弱水三千,我取一瓢饮”!

4 段—设计模式:

曾经在网上看到这样一句话:“没有十万行代码量,就不要跟我谈什么设计模式”。深以为然。

记得第一次看 Gof 的设计模式那本书的时候,发现虽然以前并不知道设计模式,但在实际编程过程中,其实还是自觉使用了一些设计模式。设计模式是编程的客观规律,不是谁发明的,而是一些早期的资深程序员首先发现的。

不用设计模式,你也可以写出满足需求的程序来。但是,一旦后续需求变化,那么你的程序没有足够的柔韧性,将难以为继。而真实的程序,交付客户后,一定会有进一步的需求反馈。而后续版本的开发,也一定会增加需求。这是程序员无法回避的现实。

写 UI 程序,不论是 Web,Desktop,Mobile,Game,一定要使用 MVC 设计模式。否则你的程序面对后续变化的 UI 需求,将无以为继。

设计模式,最重要的思想就是解耦,通过接口来解耦。这样,如果将来需求变化,那么只需要提供一个新的实现类即可。

主要的设计模式,其实都是面向对象的。因此,可以认为设计模式是面向对象的高级阶段。只有掌握了设计模式,才能认为是真正彻底掌握了面向对象设计技巧。

我学习一门新语言时(包括非面向对象语言,如函数式编程语言),总是会在了解了其语法后,看一下各类设计模式在这门语言中是如何实现的。这也是学习编程语言的一个窍门。

5 段–语言专家:

经过一段时间的编程实践,程序员对某一种常用的编程语言已经相当精通了。有些人还成了“语言律师”,擅长向其他程序员讲解语言的用法和各种坑。

这一阶段的程序员,常常是自己所用语言的忠实信徒,常在社区和论坛上和其他语言的使用者争论哪一种语言是最好的编程语言。他们认为自己所用的语言是世界上最好的编程语言,没有之一。他们认为,自己所用的编程语言适用于所有场景。他们眼中,只有锤子,因此会把所有任务都当成是钉子。

6 段–多语言专家:

这一个阶段的程序员,因为工作关系,或者纯粹是因为对技术的兴趣,已经学习和掌握了好几种编程语言。已经领略了不同编程语言不同的设计思路,对每种语言的长处和短处有了更多的了解。

他们现在认为,编程语言并不是最重要的,编程语言不过是基本功而已。

他们现在会根据不同的任务需求,或者不同的资源来选择不同的编程语言来解决问题,不再会因为没有使用某一种喜爱的编程语言开发而埋怨。

编程语言有很多种流派和思想,有一些编程语言同时支持多种编程范式。

静态类型编程范式

采用静态类型编程范式的编程语言,其变量需要明确指定类型。代表语言:

这样做的好处是:

1、编译器可以在编译时就能找出类型错误。

2、编译器编译时知道类型信息,就可以提高性能。

这种范式认为,程序员肯定知道变量的类型,你丫要是不知道变量的类型,那你就别混了!编译时,程序会报错。

Swift 和 Go 语言都是静态类型编程语言,但它们都不需要明确指定类型,而是可以通过推断由编译器自动确定其类型。

动态类型编程范式

采用静态类型编程范式的编程语言,其变量不需要明确指定类型。任意变量,可以指向任意类型的对象。代表语言:Python,Ruby,JavaScript。

动态类型的哲学可以用鸭子类型(英语:ducktyping)这个概念来概括。JamesWhitcombRiley 提出的鸭子测试可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

这种范式认为,程序员肯定知道变量的类型和它支持的方法和属性,你丫要是不知道变量的类型,那你就别混了!运行时程序会崩溃!程序崩溃怨谁?怨你自己呗,你不是合格的程序员!

动态类型的好处是:

不需要明确定义接口和抽象类型。只要一个类型支持需要的方法和属性,那么就 OK。程序会相当灵活和简单。Java,C#视之为命脉的接口/基类,在动态语言这里都视如无物!

缺点是:

1、如果类型不对,编译器也无法找到错误,而是运行时程序崩溃。

2、因为编译器不知道变量的类型,因此无法优化性能。

面向对象编程范式

面向对象编程范式,从上世纪 70 年代末开始兴起。它支持类和类的实例作为封装代码的模块。代表语言:

早期编程语言都是面向过程的。就是顺序,条件,循环,构成一个个函数。随着代码规模的增大,人们发现有必要对代码进行模块化。一个概念对应的代码放在一个文件中,这样便于并发开发和进行代码管理。

人们还发现了“程序=数据结构 算法”的规律。因此,一个概念对应的数据结构和函数应该放在一个文件中。这就是类的概念。

面向对象编程范式,确实极大地提高了生产效率,因此得到了广泛的应用,因此在语言层面支持面向对象编程范式的语言是极多的。

C 语言尽管在语言层面上并不支持面向对象编程范式,但现代的 C 语言开发都会应用面向对象的模块化思想,把同一类的数据结构和函数放在一个文件中,采用类似的命名方式。

毕竟 C 语言没有在语言层面上支持面向对象,因此就有很多程序员想给 C 语言添加面向对象支持。其中的代表是

和 Objective-C。

是一种新的语言,但大部分语言元素是和 C 兼容的。

Objective-C 是完全兼容的 C 的。Objective-C 是给 C 添加了薄薄的一层语法糖以支持接口(就是其他语言的类)和协议(就是其他语言的接口)。甚至,Objective-C 一开始的实现,就是一个 C 语言的预编译器。Objective-C 坦白讲,除了添加的语法不太符合 C 流外,实际上其面向对象系统设计是相当精妙的。乔布斯早年慧眼识珠,把 Objective-C 收人囊中,因为封闭于 Apple/NextStep 系统内,因此少有人知。随着 iOs 系统的普及,Objective-C 近几年才名满天下。

函数式编程范式

函数式编程范式,是一些数学家发明的编程语言,他们认为程序就是数学函数嘛。代表语言:Lisp,Erlang,JavaScript,OCaml,Prog。

有很多大牛极力鼓吹过函数式编程语言,认为其极具革命性。但我认为他们过高估计了函数式编程范式的威力,我并不认为函数式编程范式相对于面向对象编程范式有何高明之处。

函数式编程语言,核心就是函数,它们没有 Class 类的概念。但它的函数又不是传统面向过程语言的函数,它的函数支持“闭包”的概念。

在我看来,函数式编程语言的函数,也就是“闭包”,说白了,其实就是“类”。编程语言发展到今天,就是需要模块化,就是需要把“数据结构”和“算法”结合起来。不论何种语言,不把它们结合起来的编程方式,都是没有出路的。

面向对象编程语言,用类把“数据结构”和“算法”结合起来。类的核心是“数据结构”,也就是其“属性”,而不是“算法”,其“函数”。在类中,是函数依附于属性。

而函数式编程语言,用闭包把“数据结构”和“算法”结合起来。是函数能够抓取外部的字段。是“属性”依附于“函数”。

“类”本质上和“闭包”是等价的。现在很多面向对象编程语言都加上了对闭包的支持。观察其代码,我们可以发现,它们实际上都是用“类”来实现“闭包”的。

“类”和“闭包”谁更易用?明显是“类”。

而“闭包”更简洁一些,因此“闭包”在面向对象编程语言中常用来替换匿名类。只有一个函数的类,写成一个类太麻烦,不如写成闭包,更加简洁。

吐槽一下 OCaml 语言,其前身 Caml 语言本身是一种挺好的函数式语言,硬生生添加了一套完整的面向对象机制,同时支持面向对象和函数式编程范式,很容易像 C 一样脑裂的。

也有很多面向对象语言控看着 JavaScript 嫌烦,总是想把面向对象支持添加到 JavaScript 上。ActionScript 就是其中一种尝试。我用过,真的是和 Java 没多少区别了。

再吐槽一下 ExtJS。当初选型 Web 前端开发框架时比较了 ExtJS 和 JQuery。

ExtJS 明显是 Java 高手开发的,硬生生用 JavaScript 模拟 Swing 的设计思想,搞了一套 UI 库。

JQuery 开发者明显是领悟了 JavaScript 的函数式编程范式,依据 JavaScript 的动态函数式编程语言的特点打造了一套 UI 库,立刻秒杀 ExtJS。

由 ExtJS 和 JQuery 的故事,我们可以看到多语言编程能力是多么的重要。ExtJS 的作者精通并喜爱 Java,因此他把手术刀 JavaScript 当做锤子 Java 使,一通乱敲,费力不讨好。

函数式编程语言,还有尾递归等一些小技巧。尾递归可以不用栈,防止递归调用时栈溢出。

模板编程范式

模板编程,就是把类型作为参数,一套函数可以支持任意多种类型。代表语言:C 。

模板编程的需求,是在 C 开发容器库的时候发明的。因为容器需要保存任意类型的对象,因此就有了泛型的需求。

C 的模板编程,是在编译时,根据源码中的使用情况,创建对应类型的代码。除了 C 这种方式,Java,C#也有类似的机制,叫做“泛型”,但它们的实现方式和 C 的模板很不同。它们的编译器不会生成新的代码,而是使用强制类型转换的方式实现。

在没有模板/泛型的编程语言中,怎样在容器中存放对象呢?存取公共基类类型(Java,C#)的对象,或者 void*指针(C)即可,取出时自己强制类型转换为实际类型。动态类型语言,不关心类型,更是无所谓了,随便什么对象直接往容器里扔进去,取出来直接用即可。

一些 C 高手又在模板的基础上搞出了“模板元编程”。因为模板编程,就是 C 的编译器搞定的嘛,模板元编程就是让编译器运算,编译完结果也就算出来了。我不知道除了研究和炫技,这玩意有啥用?

小结

一门语言是否值得学习,我认为有几个标准:

1、是否要用,要用就得学,这么没有疑问的。毕竟我们都要吃饭的嘛。

2、其语言特性是否给你耳目一新的感觉。如果是,那就值回票价了。如 Go 语言废掉了异常,改用返回多值。我深以为然。我其实已经主动不用异常好多年了。因为,我觉得既然 C 不支持异常也活得很好,为什么需要异常呢?出错了,返回错误码。无法挽回的错误,直接 Abort 程序就可以嘛!而且,异常实际上是违反面向过程编程原则的。一个函数应该只有一个入口一个出口。抛出异常就多了出口了。

3、是否擅长某一个领域。如果你手里只有一把锤子,那么你就只能把所有任务都当做钉子猛锤一通。但如果工具箱里有多种工具,那面对不同的任务就得心应手多了。

7 段—架构设计

还需要掌握架构设计的能力,才能设计出优秀的软件。架构设计有一些技巧:

1、分层

一个软件通常分为:

表现层–UI 部分

接口层–后台服务的通讯接口部分

服务层–实际服务部分

存储层—持久化存储部分,存储到文件或者数据库。

分层的软件,可以解耦各个模块,支持并行开发,易于修改,易于提升性能。

2、SOA

模块之间通过网络通讯互相连接,松耦合。每一个模块可以独立部署,可以增加部署实例从而提高性能。每一个模块可以使用不同的语言和平台开发,可以重用之前开发的服务。SOA,常用协议有 WebService,REST,JSON-RPC 等。

3、性能瓶颈

1)化同步为异步。

用内存队列(Redis),工作流引擎(JBpm)等实现。内存队列容易丢失数据,但是速度快。工作流引擎会把请求保存到数据库中。

通过化同步请求为异步请求,基本上 99.99% 的性能问题都可以解决。

2)用单机并行硬件处理。

如,使用 GPU,FPGA 等硬件来处理,提高性能。

3)用集群计算机来处理。

如,Hadoop 集群,用多台计算机来并行处理数据。

自己的软件栈中,也可以把一个模块部署多份,并行处理。

4)用 cache 来满足请求。常用的内容加热 cache 后,大量的用户请求都只是内存读取数据而已,性能会得到很大的提升。

cache 是上帝算法,记得好像它的性能只比最佳性能低一些,就好像你是上帝,能够预见未来一样。现在 X86CPU 遇到了主频限制,CPU 提升性能的主要途径就是增加高速 Cache 了。

4、大系统小做

遇到大型系统不要慌,把它切分成多个模块,用多个小程序,通过 SOA 协作来解决。这秉承了 Unix 的设计思想。Unix 上开发了大量单一目的的小程序,它主张用户通过管道来让多个小程序协作,解决用户的需求。当然,管道方式通讯限制太多,不够灵活。因此,现在我们可以通过 URI,通过 SOA 的方式来让多个程序协作。Andorid 和 iOS 上的应用程序,现在都是通过 URI 实现协作的。这也算是 Unix 设计思想的现代发展吧?!

5、Sharding 切片

现在有一个潮流,就是去 IOE。I-IBM 大型机,O-Oracle 数据库,E-EMC 存储。之前,大型系统常用 IOE 去架构,在大型机上部署一个 Oracle 数据库,Oracle 数据库用 EMC 存储保存数据。IOE 是当今最强的计算机,数据库和存储。但他们面对海量系统也有抗不住的一天。

Oracle 数据库是 Shareeverything 的,它可以在一个计算机集群(服务器节点不能超过 16 个)上运行。计算机集群都共用一个存储。

去 IOE 运动,标志着 ShareEverything 模式的破产。必须使用 ShareNothing,系统才能无限扩展。

用 MySQL 数据库就可以应付任意规模的数据了。前提是,你会 Sharding 分片。把大系统切分成若干个小系统,切分到若干台廉价服务器和存储上。更 Modern 一些,就是切分到大量虚拟机上。

如,铁道部的 12306 网站。我们知道火车票都是从属于某一列列车的。那么我们把每一个列车作为一个单元来切分,就可以把 12306 网站切分成几千个模块。一台虚拟机可以承载若干个模块。当某些列车成为性能瓶颈之后,就可以把它们迁移到独立的虚拟机上。即使最终有部分列出服务不可用,系统也不会完全不可用。

12306 网站,只有一个全局的部分,就是用户登录。这个可以交给第三方负责。如可以让用户用微信,微博,qq 等账户登录。

也可以自己实现用户登录服务。还是用切片的方式用多台 Redis 服务器提供服务。Redis 服务器存储每一个登录用户的 sessionId 和 userId,角色,权限等信息。sessionId 是随机生成的,可选择其部分 bit 用于标识它在哪一个 Redis 服务器上。用户登录后,把 sessionId 发给客户。用户每次请求时把 sessionId 发回给服务器。服务器把 sessionId 发给 Redis 服务器查询得到其用户信息,对用户请求进行处理。如果在 redis 服务器上找不到 sessionId,则让用户去登录。即使所有注册用户同时登陆,也不需要太多的内存。而且,可以在 session 内存过多时,删除最早登陆的用户的 session,强制他再次登陆。同时活跃的用户数不会太多。

  • 技术

    到底什么才是技术呢?

    88 引用 • 179 回帖 • 4 关注
  • 编程
    50 引用 • 257 回帖 • 3 关注

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 25 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    238 引用 • 224 回帖
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 570 关注
  • OnlyOffice
    4 引用 • 16 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 111 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    74 引用 • 157 回帖 • 1 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 314 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 400 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 10 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    484 引用 • 906 回帖 • 1 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    25 引用 • 83 回帖 • 1 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    76 引用 • 37 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    19 引用 • 31 回帖 • 1 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    140 引用 • 441 回帖
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 356 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 608 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    6888 引用 • 31059 回帖 • 230 关注
  • 持续集成

    持续集成(Continuous Integration)是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。

    14 引用 • 7 回帖
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    28 引用 • 108 回帖
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖
  • 创业

    你比 99% 的人都优秀么?

    83 引用 • 1398 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 689 关注
  • SOHO

    为成为自由职业者在家办公而努力吧!

    7 引用 • 55 回帖 • 64 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    141 引用 • 3721 回帖 • 1 关注