免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 18638 | 回复: 23

再论 Gtkmm 与 Qt (附从底层转应用的一点感受) [复制链接]

论坛徽章:
0
发表于 2010-03-15 10:39 |显示全部楼层
本帖最后由 zx_wing 于 2010-03-15 23:20 编辑

我之前最讨厌看语言争论的,不得不说,自从开始学C++后,我就有这种恶趣味了,喜欢看人家争意思形态:mrgreen:


(Andi Peredri 为此文提供了 俄文翻译 )

再论 Gtkmm 与 Qt
(让我们期望这是最后一次了).
在这篇访谈里,Murray Cumming, 当前的gtkmm(以前被称为 Gtk--)的维护者,谈到了他认为我是为什么离开了gtkmm的,和他心目中gtkmm相对于Qt的优势。因为我不同意他那番话中说的很多东西,我觉得我应该回复一下了。

为什么我离开
Murray : (...)我猜想Guillaume从未真正地掌握gtkmm的代码基础,并抓住机会从令他沮丧的事情中逃离出来。(...)

我解释了为什么我离开gtkmm, 而且“抓住机会从令他沮丧的事情中逃离出来” 绝对不是原因之一。不过你确实几乎说对了一件事。我确实从未真正地掌握gtkmm的本质,因为这是Karl的领域,我比起Karl来说能花在gtkmm上的空闲时间实在是太少了,并且对这些时间中干的其中大多数事情都是不感兴趣的。我的目标是获得一个可以用于Rosegarden的工具包。所以我在gtkmm上的主要活动是为小部件封装打包。

gtkmm 与 Inti
Murray : (...)我认为Guillaume无论如何都确信,由于RedHat的支持, Inti会成功而gtkmm会逐渐消亡。

呃,是的,我相信Inti会成功,而显然我是错的。我相信的原因大概是我认为, 当一个开发者可以专职为一个项目工作的时候,那个项目就能进展得很快。但是这并没有发生,因为Havoc最终还是把它大部分的时间花到了GTK+ 2上。

Murray : (...)绝大多数gtkmm的用户和开发者都强烈反对Inti的设计决定

据我所知, “绝大多数”在这里是指6人左右,或者根据我在档案里读到的线索。这6人里最重要的一人显然就是Karl,他的观点我至今都还反对。我不需要一个“黑客工具箱”,我需要一个能运转的且易用的的工具箱。

社区开发
Murray : (...)Inti消亡了,因为它从未涉及到任何一个开发者社区(...)
(...)基本上,QT并不是公开开发的,所以在没有受益于任何真正的批评的情况下犯了一些错误。(...)另外也许更重要的是,如果你在使用gtkmm的时候遇到了什么问题你可以提交一个补丁或与其它开发者进行讨论。

在我看来,我认为更确切的说Inti消亡的原因是它的维护者的停止维护。对于Qt来说,确实它不是公开开发的, 你猜怎么样: 它很棒。

你似乎在暗示公开开发意味着品质。这是一个旧的自由软件的神话。一群自认为知道自己在讨论什么东西的人们(我确实曾经是当中的一员)于空闲时间相互收发的电子邮件并不能保证什么东西。但是由一群技能熟练的人组成的一个天天为难题而工作的、接收用户反馈的、能当面讨论问题的小团队很有可能达成某些好事。

让我们面对事实吧:好的程序员并不是泛滥成灾,即使是在自由软件世界。尽管区别就是很多人并没有意识到他们的真实技术水平。所以让很多人来参与困难问题的决定没有什么好处,只会让事情变得更糟。

所有的gtkmm 的设计决定都是公开详尽地讨论的,就这样仍有一些决定是错误的(像内存管理问题),这主要是因为参与讨论的人里面没有一个真正在使用gtkmm来开发实现的应用程序。我们全都太拘泥于创建一个“真正的C++ API”,而不是制作一个便于使用的东西。我在上面给出链接的Karl的帖子对于这个来说是一个极好的例子。一个由Matthew Thomas 制作、在许多网站上被充分讨论的网页日志条目,切中肯綮。它讲述的是用户界面设计,但是里面绝大多数也可以用于API的设计。无论是对用户还是开发者,界面的设计要面对相同的问题:平衡标准、美学和务实。

之所以说Qt好是因为奇趣科技(Trolltech)的开发者是很厉害的,并且他们确实听取了他们客户的意见(我知道这些第一手情况因为我是他们中的一员)。不仅如此,他们的客户在创造大型的、真实世界中的应用程序。他们的客户并不关心“信守C++精神”,他们关心的是解决实在的问题和落实应该做的事情。Qt的开发者并不试图预言什么是一个好的API以及什么不是,他们有大约2000多位客户让他们的选择面临实践的检验。

我并没有说Qt的API是完美的,它确实是有些瑕疵的。我是说它工作得非常好,我说这话的理由是我在过去两年在两个不同的项目(Rosegarden和为雇主的内部开发)上天天都在使用它。你在开发一个更好的东西的时候会比较艰难,而我并不相信gtkmm正朝着那个方向发展,感觉它的发展方向恰恰相反。

最后,你可以向Qt的开发者们提交一个补丁并与他们讨论问题,因为客户支持是他们工作的一部分。我知道这些第一手情况因为我自己就干过这样的事情,KDE的开发者们也是这样的。

Qt对C++的“扩展”
Murray : (...)这里面主要的问题是它对C++语言的修改以及对自己非标准的字符串类的使用。如我们所证实,这是不必要的。

QString是毫无疑问非常必要的,因为std::string不能处理Unicode。gtkmm自己也有Glib::ustring,我看到你把它的接口制作得与 std::string相似,这样我还是认为这是个坏主意,因为不管它有多标准,它既不方便也不强大。QString提供了非常有用的特性诸如arg()、sprintf()、section()、simplifyWhiteSpace()、toInt()和它的“兄妹”, setNum(),当然还有在日常开发中价值无法衡量的正则表达式的支持。

现在我们来谈谈长期以来颇具争议的对C++语言的修改。你也许会说这并没有必要。这是事实,尽管你还没有非常充分地证明,因为gtkmm没有提供Qt的“扩展”做到的所有特性。

信号与槽
我明确地想知道槽和信号是用什么符号表示的。在gtkmm里,它们是模版函数,是你传递给你的连接调用的东西。在Qt里它们是非常旧的const char*s。震惊!恐怖!QObject::connect把const char* 作为槽与信号的参数类型!这也就是我的第一反应。后来我认识到了两件事:

我不介意。它可能会在审美观上伤害我,但是它并不妨碍开发。
它是动态的。你可以自己产生这些字符串并在运行时再决定把连接和被连接的东西。
上面的第二点对于我来说是最重要的。它为我当时正在开发的内部应用程序节省了数周的开发时间。这个应用程序在启动的时候就根据一个XML描述文件生成了它自己的用户界面,而在这个文件里面我可以像下面这样写上我自己的代码:


      <connect source="widgetname" dest="someclass"
             signal="buttonPressed()" slot="receivedButtonPress()" />
   
需要运用的代码在半天之内就编写完毕了。如今,我认为这可以用于Qt设计师。试试用libSigC来做相同的事,看看这样会多“简单”。

另外一个这种动态性带来的特性就是松耦合。这就是说,在你调用connect函数的时候你不需要完整的类型以及源对象和目标对象的类型定义。你只需要知道它们是QObjects类。所以,假如连接是在代码中的别处实现,而不是在源对象或者目标对象的方法中,这种情况(如我在上面所描述的)下,执行它的函数不需要用“#include”语句来包含源对象和目标对象的定义。代码可以是这样:


      void do_connect(QObject *source, QObject *destination)
      {
          QObject::connect(source, SIGNAL(buttonClicked()),
                           destination, SLOT(gotButtonClicked()));
      }
   
不错,你失去了编译时的类型检查(但是你仍然可以在运行时进行检查——如果connect()函数执行失败你会得到一个警告信息),假如源对象或目标对象在定义中没有一个正确的信号或槽,在这种情况下你不会遇到一个编译错误,但是在实践中这仍旧让你能干得更快。

这种设计(两个对象之间的连接是靠第三方来完成的)是很普遍的。一旦你意识到了信号不只是为了事件处理另外还可以在保持松耦合的情况下在对象间进行通信,你就会很频繁地去使用它。

即使是由源对象或目标对象来进行连接,你仍然会成功,你可以这样:


        void MyWidget::do_connect(QObject *destination)
        {
          connect(this, SLOT(itemClicked(int)),
                  destination, SLOT(gotItemClicked(int)));
        }
      
你不需要依靠目标对象的你可以自由修改的定义。大发展又再一次出现了。为什么你认为所有新创造出来的语言,如Java或C#,拥有这种灵活性?它只是让你工作得更快。我不记得在我使用Qt的这两年里曾经被什么槽/信号相关的程序缺陷给严重烦扰过。我曾想过这种类型检测的缺失将回来找你的麻烦,但事实并不是这样。警告信息对于有效地追踪问题已经足够了。

更多有关这个主题的信息可以在Qt文档上找到。

元对象编译器和被添加的关键字
这是对Qt质疑得最多的地方。这些你必须在你的自定义类的定义和代码里使用的“槽”、“信号”、“发射”等关键字不是C++里的,并且你完全可以不用它们。是的,这是真的。不过事实是你用它们更好。它们使你的代码看起来清晰且便于阅读。

奇趣科技(Trolltech)已经给出了关于为什么Qt不为信号和槽使用模板的一个非常好的解释,这个解释我想我已经给你指出来过了。还有, 通过自己的经验, 我已经验证了他们的每个观点, 我相信, 所有其他Qt用户也一样。

不过有讽刺意味的是他们中的一个观点是语法问题。既然你一直都在制作GTK+和Co.的“C语言中的面向对象的” API,你应该比大多数人更清楚这是对的。然而你和那些认为面向对象不过是“语法之糖”的人在做一样的事。呃,就像类一样,信号和槽是定义明确的概念,因此在语言级(如果是那样的话可以说)上实现它们是有意义的,比让用户单独去对付它们好。

这样看来你对槽/信号问题的解决方法就是全部在现行C++的框架下实现它们,就像其它人在用纯C语言来实现类一样。我的解决方法就是硬着头皮和让“槽”与“信号”成为官方C++的关键字:-)。程序是用C++库还是用机器语言编写的并不重要。真正重要的是你使用添加上的东西来向编程语言表达你的设计。

使用元对象编译器这件事,在我看来并不是什么问题。如果你要写一个自己的makefile,你只需要加上一行就可以了。另外,KDE的automake宏或Qt的qmake语句也可以为你处理这个问题。在实践中元对象编译器并不会妨碍你。

Murray : (...)因而用gtkmm来与其它的C++ API进行结合更简单。(...)

你看到了用Qt与其它的C++ API进行结合时的问题了吗?在Rosegarden里我们很乐意使用STL(并且用得很多),除了STL本身的一些复杂的部分引起的问题外完全没有其它问题:-)。例如std::vector<QString>如预期般工作。

Murray : (...)我相信如果你喜欢C++,你就会喜欢gtkmm,如果你在学习C++,gtkmm就是一个更好的榜样。(...)

我不能确定gtkmm是否对于C++初学者是一个“更好的榜样”,但是你说“如果你喜欢C++你就会喜欢gtkmm”,以及你仍然没有理解为什么Qt更好,是问题的核心。我并不喜欢C++。我并不关心C++。我关心的是编写出一个能做有用事情的应用程序。所以我并不介意使用一个会向C++里添加非标准关键字的类库,只要它对编程有帮助。但是你关心C++,所以你就不能做到这点。你在乎这点却无视它的缺陷,并且你没有意识到由于对它的“坚定信仰”,你使生活变得更困难而不是更简单。另外,这就恰好是使用Gnome的C语言的程序员如何高高兴兴地去掌握GTK+的对象系统,而他们没有意识到可以用C++和Qt快得多地办到相同的事,并且彻底地确信他们所做的事是“简单”的,因为他们喜欢C语言且不需要去学习另一门语言。

标准并不是神圣的东西。理论上你最好遵循它们,但是在实践中并不一直是这样的情况,很简单,因为它们是由可能会犯错误的人类所设计出来的。工具和语言不应该被喜欢,它们应该被恰当地使用。否则,当一个更好的选择出现在你面前,你会忽略它,因为你不想放弃你自己喜欢的那一个。

Qt vs. gtkmm
在谈到这点的时候,我愿意对你在你的“GUADEC talk”里提出的观点发表不同意见。

数据容器
你说:QT有很多与现在的标准库重复的地方,比如容器和类型信息。

事实确实如此。但是:

·         自从Qt3以来,Qt的容器是与STL兼容的(例如你可以把STL的运算法则应用在它们上)。

·         一些Qt的容器确实比它们的STL上的等价物简单。例如,QPtrCollection::setAutoDelete()是很有用的。

·         你也可以忽略Qt的RTTI,并使用C++的标准RTTI。我们是这样做的,KDE也是这样做的。

内存管理
啊,又是老生常谈了。第一,你说Qt需要指针,这是错的。你可以为控件使用普通的变量(看这个例子),并且当你在使用指针的时候你可以自行删除它们。你可以这样做,而一般你不会想要这样做的。

假设你创建了一个包含许多控制和标记的相当复杂的对话类。你显然需要追踪其控制,因为你需要了解它们的状态,于是你让它们保持为数据成员。但是标记和布局控件怎么办?为它们保持一个引用有什么用呢?难道这样:


        new QLabel("Some label here", vbox);
      
然后忘记它不是更简单吗(因为你知道Qt会为你删除指针)?就我而言,确实,这样更简单。当你可以让电脑为你去做内存管理时亲自做内存管理并没有什么值得自豪的。它总会比你做得更好。

这样你就是在声称把做枯燥乏味以及容易出错的事情的可能性留给用户是一件好事,因为这是符合“正统C++的选择”。我认为这些“正统C++的选择”应该被任何一个好的C++类库隐藏起来。难道std::string和所有的STL容器会因为它们分配内存而找你的麻烦?它们不会。在最好的情况下你可以使用你自己的内存分配算符,因为有时候你可能会需要实现一些非常特殊的要求,但是这不适用于控件。所以为什么 Qt就不能有一点不一样的地方呢?

容器控件
在你的谈话中你说Qt的容器类和布局类是分开的,这正和gtkmm在容器类上的选择是相反的。我对你的观点理解得不是很清楚。Qt拥有如QVBox一样的控件,这正好像gtkmm拥有VBox,这两个控件的的行为几乎一样(你只需把控件添加到上面就行了,在Qt中这意味着以QVBOX为父控件添加一个新的控件,并不需要外加一个“add”语句)。另外,Qt拥有可以让你能进行更好调整的布局管理的(如QGridLayout,它同比它的“简化”但和它类似的QGrid相比,提供更多的选项)类。你当然可以在必要的情况下创建一个自己的布局类。

所以这样Qt明显地提供了与gtkmm一样的特性,甚至还有gtkmm没有的特性。因此我不理解你的观点。

学习和使用
我想gtkmm使你的代码更清晰也理协调。我认为它节省你学习时间并减少让你烦恼的东西。

我自己的经验直接同这相矛盾。在使用Qt两周以后,我精通它的程度比我曾经用gtkmm的时候对gtkmm的精通程度更胜一筹,约三年来我一直使用这个“该死的”东西:-)。

在这两年来我也在与那六七个几乎全转向Qt或Swing甚至正宗GTK+的“前gtkmm用户”讨论,他们告诉我的是一样的:gtkmm太复杂了,用起来太笨重了。我相信你已经在gtkmm2里改进了API,但是你无能为力的是要对付你加入的许多另外的库这样的琐事。我也很奇怪为什么Terraform这个几乎是当时唯一使用gtkmm的大型应用程序,不再使用它了。

那么让我再来谈谈我自己关于Qt的一些非常具普遍性的经验吧:所有这些Qt的非图形界面相关的类,如XML分析程序,线程处理类,日期和时间处理,正则表达式,等等,是非常有用的。Qt的开发者认为它们不实用,所以不想加入它们,但是Qt的主顾对开发者提出加入它们的要求,这是因为主顾们需要它们。没有这些特性的帮助你是编写不出一个时髦的桌面应用程序的。Rosegarden使用gzip压缩的XML作为文件格式。XML是一个显而易见的选择,大部分是因为Qt拥有一个它的分析器。要用gtkmm做相同的事,我们需要与libxml连接。这意味着另外一些拥有不同API和或多或少文档……等等的库需要处理,我们甚至有可能需要封装它,这又会导致更多的代码。

这实际上正代表了我使用gtkmm开发Rosegarden的无益尝试(见Rosegarden开发历史以获得更多细节)。我一开始试着创建一个可以把音符显示在上面的简单的控件。但是等一下,我必须创建一个没有多少实用价值的音符的位图,并且要做到这点我需要使用GDK和imlib,它们中没有一个在当时是已经被封装的(而且封装者使用了一个与gtkmm的其它部分完全不同的内存管理策略)。于是我首先要向这些封装者里加入材料。接下来我需要Gnome Canvas来把谱线和音符显示到上面去。这又是没有封装的,所以又得封装。这此这般,令人非常之不爽。现在libxml、vfs和其它我们用的工具也是一样的,KDE提供了它们,而它们的Gnome中的等价物还没有被封装(另外我这里使用的“等价物”一词所指得东西比较宽泛)。

在转向Qt/KDE后大概一个月里,我取得的进展比过去3年还大。一段时间后,Chris和Rich重新加入进来,现在我们仍然进展稳定,因为程序架构并不妨碍,甚至对于相当难的像IPC一样的东西也是这样。DCOP运转得太好了,从甚至不知道该做什么事情的时候起,让Rosegarden对DCOP的消息有反应,仅仅用了我20分钟(我没有撒谎)。大多数的用户界面问题在几小时之内就解决了,这样我们就能集中精力对付实际的问题。刚才我随便写了一些关于Rosegarden的开发的不是很有条理的想法,如果你需要更多的细节你可以去查阅一下。

关于“节省学习时间”,看看gtkmm的这篇关于内存管理的页面。和Qt的内存管理比较一下。

总结
Murray : (...)Guillaume现在使用QT。他声称对他来说拥有一个完美运转的工具比一个完美的API更重要。gtkmm2将很快变得稳定——这样我们就可以在gtkmm2里同时拥有易用性和完美的API了。

是的,我使用Qt/KDE,并为此感到高兴,因为经过了这么些年Rosegarden开始看起来像一个真正的应用程序,which has always been the point. 这在使用gtkmm的时候是绝对不会发生的。

和你所说的相反,gtkmm2离可以提供相同级别的特性还有几年的差距。如果它能达到,它也会付出巨大的资源代价,因为你必须把每个库都添加到封装者里。即使拥有gtkmm、gnomemm、bonobomm(它暗示了与所有它们所封装的Gnome的库所连接),你仍然没有得到Qt及kde库的所有特性。看看一个简单控件的层次结构,我数出了4个如下的“对象”:

SigC::Object
Glib::ObjectBase
Glib::Object
Gtk::Object
人们会对它们的内存冲突感到惊讶。

另外一个问题,即使gtkmm这几年来一直稳定,为什么使用它的应用程序却很少呢?

我们大约一年前进行过相似的讨论。看起来你的观点还是没有改变:你因为个人喜好的缘故不喜欢Qt,但是你仍旧对为什么使用它就会让你的代码难于编写和维护这点没有一个清晰的论据。我的经验是Qt使编写及维护代码成为一项简单的任务。只要看看由它产生的软件的价值就知道了。如果gtkmm被如此广泛使用,你就会在这方面得分。这是自由软件,所以更好的技术应该流行,是吧?

你不喜欢Qt,因为它不符合你心目中一个C++类库应该遵循的标准,如此而已。我认为你的想法是错误的,gtkmm正好重复了这类让C++获得“艰深易错的语言”名声的错误:自身不够详尽和把太多的东西留给用户。

如此我祝你的gtkmm2好运,但我还要继续使用Qt/KDE并在Rosegarden上帮助Rich和Chris。


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

P.S. : 一个gtkmm常见问题 #2.4的“补丁”
下面是对关于一些项目的回答的修正。

gtkmm使用std::string、std::list、std::vector、iterators,等等。Qt使用自定义的容器。
这是对的,但是:

o        QString使用起来在功能和便利性上大大优于std::string,另外它是基于Unicode编码的。实际上你的确不能对用户可见的字符串使用std::string,除非你计划从不使你的软件多国语言化并使它仅仅保持为英文版。

o        容器在大多数情况下是作为一个没有好的STL运行环境的平台的代替品。它们确实拥有几个便利的特性(如对基于指针的容器的“自动删除”),但是通常你的确不会使用它们,除非Qt的API需要这样。它们也是兼容STL的, 这意味着你可以对它们使用STL的运算法则。只要把它们视作另一种容器……

在gtkmm里可以使用普通的C++内存管理。Qt需要把所有的控件都视为指针来进行处理,并且控件的删除交由父控件来处理。
上面的话彻底错了。你可以把控件视作变量来处理,不过显然这样做在及个别情况下才有意义(如创建一个对话框),另外你也可以在需要的时候自行删除控件。

gtkmm的控件的安排更加简单。在Qt中,容器和布局是分开的类,子控件必须被同时添加到它们两者中。
这也是错的:看看QHBox、QVBox、QGroupBox和QGrid。只有在你需要对控件如何放置有更高要求的时候,布局类才是必要的。Qt的布局类同样拥有一个autoAdd标志位,这样可以减轻你向它们或父控件添加控件时的工作量。

Guillaume Laurent
最后修改:2004年7月28日 星期三23:46:07 CEST

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
发表于 2010-03-15 12:36 |显示全部楼层
c++,一直没有信心学好它,怎么办呢

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
发表于 2010-03-15 12:40 |显示全部楼层
本帖最后由 smalloc 于 2010-03-15 12:45 编辑

LZ的转型让我等不得不正视自己正视现实...
LZ不妨出一篇关于转型的帖子...从体系结构转到应用开发的因素.以及国内在这2方面的差异.

论坛徽章:
0
发表于 2010-03-15 14:39 |显示全部楼层
LZ的转型让我等不得不正视自己正视现实...
LZ不妨出一篇关于转型的帖子...从体系结构转到应用开发的因素.以 ...
smalloc 发表于 2010-03-15 12:40


哈哈,既然兄弟你问到了,我就说说,反正这也是个水贴
我是被迫转型的,由于项目变动不得不做应用层开发。刚开始很痛苦,完全提不起兴趣。我之前有着国内大多数初出茅庐的技术小青年的通病:觉得做底层很牛B,做应用开发门槛低,没前途。于是我迷茫啊,消极怠工啊,继续钻我感兴趣的底层,转型3个月后我觉得不能忍受了,于是准备跳去做solaris的kernel(虽然当时sun已经风雨飘渺了)。后来和几个资深的长辈聊了几次,又没去(主要当时大家都不看好solaris,觉得sun一倒它迟早要被干掉)。
后来我接手两个项目,都是做中间件,我白天coding一个项目,晚上coding另一个。这个时候我态度已经端正了,准备老老实实的做应用开发。这个过程中,我才发现原来应用开发的难度远远超出我之前幼稚的想象。由于之前我没有相关经验,很多问题我根本就不知道业界通用的解决方法是什么。之所以说“业界通用”,是因为在面对一个未知的问题时,我会首先去看已有的、成功的开源项目在解决这个问题时是怎么处理的,而不是自己想当然写出难看的Code。于是我花费了很多开源项目的Code,其间读的很痛苦,因为很多库我都不熟悉,比如glib。做底层的经验给我带来的一个坏毛病是:喜欢钻牛角尖。比如当初我在用glib的event loop的时候,搞不清楚它怎么实现的,于是花很多时间去看glib的code,这耽误了我不少功夫。另一麻烦就是应用开发的很多工具不会用,例如autoconf/automake/libtool这一套,也花了不少时间学习。总之是个非常艰难的转型,远不是当初想象的底层转做应用就是牛刀杀鸡一样,难多了。
现在转型已经两年了,自己有一些经验。

1. Kernel is not difficult, it's just different
这话不是我说的,忘了是哪位大牛说的了。这里借用这句话,kernel泛指底层开发。说实话,要一辈子吃底层饭,绝对比一辈子吃应用开发的饭简单多了。原因在于底层开发是个收敛系统,应用开发是个发散系统。底层受限于硬件,虽然有不断的新feature,但相比应用层技术的革新,那真是慢太多了。在底层开发,时间越久经验越多,可谓一艺通,百艺精,你在一个子系统的经验很容易扩展到其它子系统。应用开发就不一样了,很多需要专业知识,例如你multi-media搞的再精,也扩展不到语意网搞搜索。此外说底层开发收敛,是说在一个code base的基础上,你要的东西都可以找到。例如你在内核中看到一个函数,就可以在内核中找到实现。而应用开发发散,当你看到一个没见过的函数时,很可能就意味着你要学习一个新的库了。

2.国内大多数搞底层的人,涉及不到架构设计,只是修修补补
这个是现状。当然你的patch被kernel接收,那是很牛的,每年能贡献10几个patch,如果在国内是独立开发者的话那肯定是很有名的人了。但即使这样的牛人,我认为他也无法但当起应用开发中architecture的角色。为什么?他缺乏大型项目的经验。搞底层的code量很小,如果是发patch,上千行那是非常不得了了,基本上是在改写子系统。通常也就几行、百行左右的规模(当然,虽然code量少,但却是涉及的内容广)。但这和应用开发中的架构设计完全不一样。应用开发没有个几万行(对于小项目)、10万行以上编程经验,拿到一个项目,要做架构设计,基本不可能。考虑的东西太多了,这是应用开发的业务复杂决定的。一开始没设计好,随着代码量的增多,后来改就太麻烦,太难了。特别是做中间件,一开始可能你API文档都release出去了,在实现过程中发现不对,要改,这对使用你库的用户来说简直是不可能接受的。这也是为什么我在做项目前要大量调查已有的开源项目如何解决问题的原因。因为我之前的code量少,没有这种设计经验,所以我不得不大量阅读好的项目的代码,从中学习。

3.应用开发涉及太多的专业知识
例如前面举例的multi-media、语意网。很多时候你要花大量时间学习业务,这和底层学习硬件原理类似。不相同的是应用开发的业务很多没相通性,也就是说你无法重用你之前的经验。而硬件的相通性非常大的。

4.应用开发需要更多的技能
做底层把C搞精,再加个汇编,基本就行天下了。应用层就不说了,不是一门语言能解决所有问题的,不然我也不学C++了。

以上几点是我转型中感到底层转应用的难处。下面说几点好处:

1. 自下而上的学习,比自上而下的学习简单多了
抛开业务,仅从technical的角度讲,底层转应用,可能开始要学习的东西很纷杂,但能很快明白它们内在的机理。因为你有操作系统的知识,你知道系统是怎么运行、程序是怎么跑的,所以你知道哪些事情在现有的计算机体系下可以做,哪些不能;哪些事情是编译器的工作、哪些是操作系统的工作,不会问出“假设我有一个打开却忘了关闭的文件描述符,编译器能不能检测到这条语句,在后面加条语句关掉”之类的问题。如果一开始就做应用开发,又没有刨根问底的精神的话,很容易停留在问题的表面,而忽略了技术背后的实质。

2. 你能写出更好的程序
这也是源于你的操作系统知识,在涉及到效率、性能的问题上时,你知道该如何写出好的程序。

3. 对于应用和内核交互的程序,你会得心应手一些
这是很明显的。

说一个应用开发烦人的地方:当你把架构设计好,业务熟悉后,很多工作就是体力coding,久了烦躁

以上就是我的一些经验。从这次转型,我觉得从对技术的认识上成熟了,不会轻视任何一项技术,也不会觉得任何一项技术是高不可攀的。例如我有个朋友,CSDN的web专家,对我说PHP没什么难的,很容学,门槛低,言下之意没什么意思。但我觉得问题本身不在于这个语言的门槛如何,而在于你有长期的web经验,加上你熟悉这个语言,于是你可以用它快速的解决问题,你的价值在于你知道很多业务在这个背景下业界如何解决,不在于市面上学习这门语言的人有多少。又比如我以前觉得搞算法的很牛B,高不可攀,但我现在认为只是我们从事的工作不同而已,只要不是搞数学研究的,大部分做算法的还是把现成的、经典的算法加以运用而已,这和懂很多硬件知识没有本质区别。

最后要说的是往应用走比往底层走,路宽些,说俗点就是容易发财些
此外对于很多搞应用的朋友,浮躁的缺点要避免,多把自己的项目搞深入点,不要做的多,懂的少。每做一个项目应该得到得收获是,你知道了业界对于这种项目通用的方案是什么,并且知道细节。当你做的项目多了后,你的经验累积那不得了,可以当consultant了:wink:

最后举个我老大的例子,当年我还啥都不懂时他带我出道的。我老大现在移民美国,在硅谷发展,走之前是世界最大存储公司的principal engineer。他底层搞得很深,简历里写“A lot of knowledge in system architecture, such as x86/ia64 architecture, MMU, cache, PCI, power management, ACPI, BIOS, RAS, SMP, IOMMU, NIC and VGA etc..”,上次听在美国的朋友说他感叹说自己的知识面太窄了。由此可以见底层的知识面和应用的知识面纯粹是两个范畴。

评分

参与人数 1可用积分 +10 收起 理由
OwnWaterloo + 10 我果然没看走眼~

查看全部评分

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
发表于 2010-03-15 15:11 |显示全部楼层
本帖最后由 chenzhanyiczy 于 2010-03-15 15:14 编辑
哈哈,既然兄弟你问到了,我就说说,反正这也是个水贴
我是被迫转型的,由于项目变动不得不 ...
zx_wing 发表于 2010-03-15 14:39



顶!

lz的造诣很高啊

多谢分享经验,给我很多提示了

能做Solaris 内核曾经是我的梦想

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2010-03-15 16:13 |显示全部楼层
回复 1# zx_wing

1. QString

我确实很反感这玩意。 还有什么QChar……

2. signal/slot

既然都做成运行时类型检查了, 直接使用其他语言不更好?

论坛徽章:
0
发表于 2010-03-15 20:12 |显示全部楼层
哈哈,既然兄弟你问到了,我就说说,反正这也是个水贴
我是被迫转型的,由于项目变动不得不 ...
zx_wing 发表于 2010-03-15 14:39



    NB文章,佩服啊,让我这半路出家的菜鸟搞清楚不少事情

论坛徽章:
0
发表于 2010-03-15 23:46 |显示全部楼层
回复 6# OwnWaterloo


    >>2. signal/slot

>>既然都做成运行时类型检查了, 直接使用其他语言不更好?
这是什么意思?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2010-03-16 00:07 |显示全部楼层
回复 10# zx_wing

楼主最近很闲嘛~

意思就是说, Qt实现的这套东西, 其实已经实现了一个简单的类型系统。
那为什么不直接使用一些更灵活的语言?
这些语言有更完备的类型系统, 更专业的维护人员。
而且有更强大的功能。

也就是说, 将需要效率的部分, 让C或者C++与底层通信。
然后让这些非常灵活的部分, 交给其他语言去开发?
比如PyQt?

论坛徽章:
0
发表于 2010-03-16 00:41 |显示全部楼层
楼主关于底层和应用的见解,深有认同。
其实QString和gtk+的gchar*又有多少分别呢,不过是对类型在应用实践中的抽象
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP