| |
文摘:程序设计大概是目前大家都会遇到的事情,那么怎样才能真正掌握这门基础技能呢?本文作者从语法、语义、语用三个方面分别进行阐述,展示给我们他在学习过程中的诸多心得。
首先要说的是,无论是资历还是技术水平我都还远达不到那种可以拨云见日、指点迷津的境界,里面更多的可能是个人的经验和心得,如果有人看了之后,能有所思考,有所收获,那我的目的就达到了。:)
先说语言吧。程序设计语言可以说是人机沟通的一个特定界面,每种语言的产生和发展都有其特定的应用背景。正如黑格尔所说"存在即是合理",当前的各种主流语言都在其各自的应用领域里发挥着特定的作用。因此,脱离应用背景而简单的把两种语言进行优劣比较是没有意义的,而且常常会有其他主观、客观因素影响,使得这种比较"无可救药地偏向某一方"。这是我要说的第一点。
其二,是语言的学习过程。首先一点,就是选择好目标。语言的种类繁多,设计思想更是千差万别,有面向过程的、面相对象的、函数式的,规约式的等等,如果有时间,不妨从每一类中都挑选出一个或两个比较有代表性的、主流的语言进行学习和了解。当然从实用的角度来看,首推目前运用最广泛的面向对象语言,这类语言最具代表性的非C++和Java莫属了。C++是从C演化而来,为了保持对C的100%兼容性而保留了很多面向过程的特性,因而常有人说比起C++,Java是更加纯粹的OO语言。但是,这决不说明C++对OO的支持不如Java,相反C++甚至为程序员提供了更为高级、灵活、复杂的特性(比如MI和Template),也正是这些特性和其与生俱来的对底层操作和控制的支持(比如内存指针)混合在一起,使得整个语言变得非常复杂(error-prone),这也就是C++常常遭到抱怨和责难的原因。从这点来看,C++就像是一把轻巧灵活,但却锋利无比的双刃斗剑,纯熟运用的剑手可以发挥出其巨大的威力,而初学者却往往会被其锋利的背刃所误伤。然而,从纯粹学习的角度来看,我本人更推崇C++语言。通过对c++的学习,除了掌握一般的OO的思想方法之外,还能从中(比如this指针,extern "C",vtable, call method directives等等)窥探出OO的实现细节,了解到在一个普普通通的member function call的背后究竟发生了什么。这些知识一方面可以加深对OO的理解,另一方面也有助于写出更为高效、出色的代码。
选定目标之后,接着就是漫长而艰苦地学习过程。按照编译原理的说法,语言可以分为语法、语义、语用三个方面,语言的学习基本上也是从这三个方面(或曰层次)由浅入深,循序渐进,往复循环的过程。
语法应该是最基本,也是最容易的部分,但是某些语言的语法,比如C++,可能远比我们想象的要复杂得多,如果你认为像这样的语句不算什么的话:
template<class _Ty, class _A = allocator<_Ty> >
class vector
{
explicit vector(size_type _N, const _Ty& _V = _Ty(),
const _A& _Al = _A())
: allocator(_Al)
{
....
}
....
}
那么这两句怎么样:
typedef INT;
typedef *PVOID;
当然,在实际的软件开发中应该尽力避免这类晦涩的语句,举这样的例子只是为了说明c++语法的复杂性。语法的学习决不应该被忽视,尤其对于像c++这样的语言。
正如日常用语中种种含蓄和暧昧一样,程序设计语言的语义也决不会像标准里规定的那么简单和直接(plain and straight) (我这里说的语义的意思可能比编译原理里的定义要更广泛一些)。比如在c++里 class D : public B不仅仅意味着D将继承B所有的public和protected接口并保持它们的属性,更重要的是A publicly inherits from B means "A is-a B",又如:A pure virtual function means that only the function's interface is inherited (for more details, consult effective C++ item 44). 因此对于语义的学习不应停留在语言表面定义上,更重要的在于理解某些惯用表达方式背后的深刻含义,正如Scott Meyer所说的,Say what you means, understand what you are saying (again, effective C++ item 44).
另外,就是语用了,也就是牵涉到使用语言来解决问题的技巧和方法。在这方面,Design Pattern为OO语言提供一套严谨、有效的方法论,围绕"如何设计可重用的软件系统"这个中心,讨论了OO技术在工程运用方面的种种技巧。比如,如何隔离系统中易变(volatile)的部分,如何改造一个已存在的类的接口等等。除了这些正规的方法论之外,还有种种广泛流传的trick,这方面C++特别多。
语用的学习决不是一朝一夕的,而应该是在实践的基础上不断进行总结、评价并逐步积累和深化的过程。
最后,还想说的是,这三个方面并非是完全独立的,它们之间也没有存在非常明显的界限,因此是不应该被割裂开的。如果用软件工程的开发模型来比喻学习过程,那么我更推崇不断循环、不断深化的螺旋型,而不是泾渭分明、一气呵成的瀑布模型。另外,在学习中,实践起着非常大的作用,只有coding到一定程度,再往回看,才会真正明白这种语言的妙处,才会真正建立起一种编程思想。
|
|