在知乎回答 “C++后端程序员如何赚外快”时,提到了如何用C++签下并完成一个三十万的Web应用。有一些人感兴趣,当然我们程序员视金钱如粪土,所以主要感兴趣的是: C++工程师如何开发WEB应用?
一直没时间去梳理,不过问的人多了后,我想还是好好地把“C++”和“Web应用”这两个放在一起会有神奇化学反应的东西扯一扯。
先说一段相关历史事实:最早有像样的互联网络时,Web后端程序还真是主要以C++写成。对C++的cout重定向处理,写这么一句我们超熟悉的:cout << “hello world” << endl; 很快,对世界的问好就显示在浏览器的页面上。这种开发模式基本消亡了。我想的并不是简单地复活这种模式(CGI)。
一. 从C++的一点光辉历史看它的一些特点
C++一开始可是头一号明星语言,在跑道拉开第二名(换来换去)好几圈。那时候一切的竞争基本是围绕这家的C++和那家的C++之间进行竞争。有关这段故事的回忆,有兴趣的同学可以找找李维先生写的《Borland 传奇》一书翻翻。
C++当年的地位当然也不是因为它真是百般好,更多还是时势造人。那时候的商业软件多数是单纯的图形化桌面软件或C/S结构的软件。而要在桌面上开发图用户界面(GUI)软件,程序主要需要和操作系统打交道(Windows、Linux、UNIX 等)。而又由于C语言在编写操作系统方面近乎蒙古帝国般的一统江山的局面(这个局面形成的原因超出本文闲扯范围),所以操作系统提供给上层应用的功能接口都是C风格的。比如要申请系统内存、要创建个按钮,要玩鼠标、要播放声频视频、要画条直线等。C/C++都可以方便,高效地调用操作系统的接口。自然在推广上会占便宜。
当然,操作系统能选择C语言开发,倒过来也说明C语言有过人之处,同样我们不展开讲。C适合搞底层的东西,相比之下倒是不太适合搞上层的东西。什么是底层?就是机器系统里的东西。什么是上层,就是人类社会的东西。从技术角度看,底层涉及的东西往往更专业技术化,所以会说底层难,会说底层复杂。可是,如果从处理的对象种类之多,对象之间的关系之错综万变,显然是靠近人类的上层更复杂,更善变,更难以描述。所以,软件行业的正儿八经的科学家们用C等面向过程的语言开发不少业务之后,开始提出“面向对象”的思想。C++赶上着这个需要,嘴里衔着“面向对象”出生,多了一份流行因素。
另外,在C++年轻气盛的时期,软件还主要是单机的,所有功能揉在一起;或者是C/S结构的,Client 端主要和操作系统打交道,以创建用户界面。Server端主要和数据库打交道以及按业务加工处理数据。两者之间则采用网络通信。由于C++可以直接调用操作系统的功能,界面也好,数据库也好,网络也好都没问题了。又由于C++有“面向对象”特性,确实也可以处理较复杂的关系;因此大家也就一直用着。
总之,沾了C语言的光,沾了操作系统的光,沾了的“面向对象”的光,好像是这些特性让C++在当年成了编程霸主。不过今天这里主要讲的“光”,是指C++的流行,沾了曾经的单机、C/S结构、分布式这些应用体系架构的光。如果我们把C语言、操作系统、面向对象思想、涵盖“单机、分布式、C/S”的软件结构,以及C++自身,画成五颗帝星,那么C++曾经深得其它四星之普照,因而曾久居帝位,光芒万丈。
二. C++的“没落”,以及为什么Web开发不搭理它?
C++的“没落”,是上面四颗星陨落了吗?还是星光依旧,只是所照非人了?
如果只是简单回答说,C++“没落”是因为有新的更好的语言,比如Java、C#代替它也,那就多少流于表面了。
操作系统还是那个操作系统,还是一个身怀许多功能的胖客户端。操作系统还是基本使用C语言编写,甚至有了更多C++参与的成份,也还保留了对外的C风格的接口。但是,操作系统被架空了。
当我们说到“某某某被架空”这样的话题时,可不能光想到的技术。所谓“架空”的背后往往是一出复杂的宫廷戏,没版面细说。操作系统被架空一事,这近三十年来,一直就是一拨又一拨的IT行内的人士,"有组织、有计划"地反复在做的事。这三十年来,为架空操作系统这一事业而奋斗终身,或偶有小得,或近乎黄袍加身而惜败,甚至青史留名而粉身碎骨者,一幕一幕,可歌可泣……当然,也这超出本文的范围,但任何一位有志于在IT行业、特别是互联网行业鹰击长空年轻人,我推荐在学习技术之外,一定要学会读史——反正IT从业者怀念祖辈的时,通常也就提到父亲最多爷爷那一辈就程序退出了,不像那些搞医学什么的,言必从黄帝内经说起。培根说“读史使人明智”,如果从事IT行业却不读IT史,我们就不明智,为什么不明智呢? 这回得听唐太宗的,他说“以铜为鉴可以正衣冠;以人为鉴可以明得失;以史为鉴可以知兴替“。如果从事IT行业却不了解IT发展史,那有一天我们所掌握的工作技术被代替、我们用以养活家庭的的工作岗位被别人替换或架空了,都不知道这是为什么。
谁架空了操作系统?现在全天下人都知道是浏览器。浏览器是IT界的司马昭?
皇帝一开始担心的,估计并不是司马家族,毕竟他还是朝中人。皇帝曾经担心过另一些操作系统叫嚣着要取代自己,或者搞个半壁江山或三分天下。但那些个操作系统真的很弱——基本只能在台后干活(这个很重要,终将影响历史的车轮),台前没讨得几个百姓欢心,那感觉就像硬把江南才子往塞北赶一样,不习惯。
司马家族一开始当然也弱。像是芝麻小官把守边疆,负责外部世界打打交道。皇帝想,大天朝地大物博,有什么有什么,子民们哪个需要,哪个喜欢和域外打交道呢?一时新鲜而已……未料那司马家竟然边疆私设市场,还在朝里设了个“快捷方式”,别说子民了,连皇后娘娘闲着也去逛啊。这还得了!朝里派出小舅子,另设边界贸易市场,同时派人不断暗中骚扰司马家市场,三下五除二搞垮了司马一代。
然而,一个司马家族倒下了,千万个司马家族站起来了……火狐、谷歌等等的加入,皇帝的小舅子最终扶不起了。
以上是对操作系统被浏览器架空这一历史事件的政(八)治(卦)解读。接下来回到技术解读。
浏览器在哪些方面架空了操作系统 ? 假设我们要做个软件,能显示一篇文章,一张图,或者一个列表,还要在哪里有一个按钮,以前这些统统由操作系统实现,程序调用操作系统的开发接口。但现在这些事在某些应用里,都交给浏览器干。浏览器倒基本都是用C++写成的,但让浏览器开放出来的接口却和C/C++语言无关,而是和HTML、CSS、JavaScript有关。
以创建按钮为例,想让操作系统干,大概得用C++写如下代码(仅示意):
Button* button = new Button("点我!");
而C++背后调用的C接口可能是:
HANDLE h = CreateButton();
SetWindowText(h, "点我!");
但是,想在浏览器显示一个按钮,写的代码是这样的:
偏激一点,这甚至不能称为源代码。就是一个文本,浏览器每次读入这行,然后在页面某个位置就显示出一个按钮。这中间和C++语言没有任何关系了,当然和C#或Java也没有关系。虽然Java一开始是想在浏览器干点这类活的,但那是真是逆向行驶,很快放弃了。倒是有Flash技术借着做动画的本事,逆行了一段距离,但最终也消亡了。
客户端不再开发部署程序,直接把界面展示和人机交互的工作,交给浏览器实现,并由浏览器负责和后台交互,这种模式就是B/S模式。
B/S当然也不是仅仅搞个浏览器当客户端这么简单,它的背后其实反应了一些开发技术发展的方向。各个方向对C++都有些影响:
1)前端(和用户直接打交道的客户端)重点负责界面,展示数据以及和用户之间交互。这些工作所需要用到图形界面、网络交互、内存管理,缓存处理、异步操作等技术已经相当成熟,模式也相对固定,可因此可交给外部运行环境,比如这里的浏览器来实现。通过HTML、CSS这类标签式的语言,附加JavaScript这样轻量的脚本与浏览器合作完成。之前这些是由C/C++与操作系统紧密合作,共同完成,没有C++什么事了——当然严格讲还是由C++在完成,因为浏览器也好,JavaScript的运行引擎也好,基本都由C++写成。
2)前端负责数据展示,而数据由后端负责生产加工处理再“吐”给前端。前端就是街上大大小小的水果铺,它们负责把水果排列好,让客户看着就想买,但水果是后端提供的。这个模式叫数据的展示和数据生产处理分离。无论是B/S还C/S模式基本都讲这个理,因此这个模式本身并不排斥C++。我们打开QQ时,显示朋友列表,来但C++写的QQ后端。真正对C++产生较大影响的开发发展方向是: 前端和后端之间的对话需要标准化,并且是开放的标准。一旦标准化后意味着什么?意味着前后端如何对话的过程公开透明,不会随便乱变了。也就意味着我们可能被剥夺自行实现这个过程的权利。因为会有比我们厉害的人提供近乎标准的实现。历史上家庭用电都曾经每家每户自行建发电厂,后来呢?对于B/S结构的前后端,这个标准通常就是HTTP协议,浏览器包办了一切,没有C++什么事了——当然严格讲还是由C++在完成,因为浏览器也好,网络通信模块也好,基本都由C++写成。
3) 前端负责展现数据,后端负责提供数据,中间使用标准协议(车)和数据报文(货)进行通信。听起来是完美了,但还不够,还有一个看起来只是锦上添花,但其实非常关键历史发展洪流下新时代的要求:前端展现时的界面数据(比如页面排版结果),也由后台给出。这样做大有好处。比如,新浪网页平日里五颜六色的,遇上汶川大地震纪念日时,想将页面颜色变成灰色,总不能给全中国人民打电话教他们如何在自家的电脑上改颜色吧?而是在新浪服务器端改一改,全国人民打开页面就看到不同颜色了。
归纳一下:1) 前端展现数据,2)后端提供数据,3)前后端间使用标准的通信,4)后端提供的数据分成两种,一种是和展现有关的数据,比如布局,颜色、字体等,另一种才是真正的业务数据,比如今天的头条新闻、股价趋势等等。
这些技术方向中哪几点动到了C++语言的奶酪呢?看一张表:
进一步归纳:
1)B/S结构的出现和流行,抢了C++在桌面端的活。早先程序基本是单机版或C/S结构。B/S结构出现之后,动了C++的奶酪。是因为确实有不少类型的应用系统很适合采用B/S结构。这个变化只动了C++的奶酪,动不到Java等其它主流编程语言,原因很简单,因为这块奶酪基本一直就在C++手上。
2)“不好学,不好用”的名声,影响了C++在后台的开始。加编译出来的二进制代码无法跨平台运行,因此影响了它在Web后台开发的地位。哪怕Web后台其实有大量C/C++开发的工具程序,比如 Nginx、MySQL,redis、memcache、等神器,全世界恐怕90%的Web应用选用了它们(全部或部分)。另外,这些神器多数都有跨平台的实现。
3)“界面数据“和”业务数据“在后台组装,这样一个细节,居然也影响了后台开发不选择C++。在后台组装这两样数据是相当拙劣的设计。你是果农,生产苹果、桃子、梨子,但你在销售这些水果的同时,竟然被要求把人家水果店的柜台甚至店面装潢都做出来,摆上水果,然后一并送过去。这是赤裸裸耦合设计,是严重扯不清前后端分工的做法。
我的狼子野心大家应该能读出来了:Web应用和移动应用是当前大热门,并且它们都需要后台,所以我想让C++在Web后端开发夺回一杯羹。这里的后台开发当成不是指C++现在就处于近乎统治地位的后台底层支撑开发,而是指赤裸裸的业务后台开发。等下,仅仅是这样一个善良的小企图吗?不止。C++开发的纯业务后台,应该能够同时支持Web前端和移动APP前端 。比如开发一个在线店铺,如果既要在微信公众号开微店(Web),又要有自己的手机APP(安卓或苹果),那应该是同一套后台实现。说起来这企图也相当的合乎人性嘛,谁愿意一件事做两次呢?微信的微店就像是在超市里租个水果柜台,APP则像是在路边开的水果专卖店,但对于后台来讲,我们都只愿意提供水果。
要实现这“狼子野心”(其实完全是一个正常的、普通的C++程序员应用的心声吧?),当然得面对上述归纳的三点问题,如何解决呢?
1)B/S 结构抢了C++前端(桌面)开发的问题。这其实不是个问题。一来我们现在说的是用C++做后台业务开发。二来,B/S和C/S本来就不是谁替换谁的问题,而是谁合适就用谁。比如较晚出现的苹果手机和安卓手机的APP开发,出于性能、安全以及管理(包括收费的方便性)等需要,又回到C/S模式。
2)C++难学难用的问题。确实C++是比较难搞。不过如果你已经是C++牛人了,那这个问题就自然也不是问题了,甚至是个优势,因为难学难用的C++倒也具备可以搞定其它易学易用语言可能觉得很难的问题。剩下的问题正是文章篇题所说的,如何增值你掌握C++编程能力这个问题,我们不能让C++成为屠龙技嘛。
3)那如果你有兴趣C++,但刚学不长时间怎么办?这个要安利一下我的书《白话 C++》,现在分成上下卷,年内会面市了,至少是上卷。北航出版社。
4)C++不能跨平台问题。现代的C++其实在源代码层面已经很好跨平台了。另外更多时候跨平台是一个“客户没问题我们也创造出问题来解决”的问题。谁家Web后台一定要windows服务器和Linux服务器各搞几台呢?
5)最后一个问题才是真的问题:我们要让C++写的后台程序,也负责拼装界面数据和业务数据吗?这个其实也有许多C++的开源方案,但我一个都看不上眼。不是它们在这个方向上做得不好,而是这个方向本身就是坑爹的。
这么一分析,只要搞定上面第5点,用C++开发WEB后台,出任公司CTO,迎娶白富美的日子似乎就来临了? 别忘了还有政治问题!如果你只是公司里一个小开发,我们要怎么让做Web项目的经理及同行同意你加入项目用C++帮他们搞呢?怎么让他们相信你不是来捣乱的 :) ?
想想也挺难的,所以文章还想讨论一下“如何成为在团队里有影响力的软件工程师”。
不管技术问题还是政治问题,我们下一篇再继续。