软件开发的形体与魂魄(之一)(100)

  • 主题发起人 主题发起人 xiaorang
  • 开始时间 开始时间
X

xiaorang

Unregistered / Unconfirmed
GUEST, unregistred user!
  从事软件开发十年多,回想以前开发过的软件,几个不同行业的信息管理系统,机器人开发工具,LOGO语言编译器,游戏软件,教育软件,天文软件,各种各样的工具小软等等。并不曾致力于深入一个行业,而是一直立足于纯然的软件开发本身。乐于研究软件开发自身的逻辑,自以为有一些感受。本文将尝试从一个不同视角来看软件开发的各个方面。以Delphi语言开发的软件为例,但其分析方法可以用于各种编程语言。软件的形体  软件真的有魄与魂么?任何事物复杂到一定程度程度之后,都会有一些新的概念出现,魄与魂正是一种典型的复杂形态的称谓。所以这是真的。不过在研究魄与魂之前,我们不得不先研究魄与魂的表现载体,软件的形体。  如同现代医学通过人体解剖的方式永远搞不懂经络概念,因为经络只存在于活动的生命体之中。  说到软件的形体,同样有两个含义,静态的与动态的。所谓静态含义,是指软件的磁盘载体(即磁盘文件),这就好比是解剖台上的软件结构;所谓动态含义,是指软件运行时的内存结构,那才是活动中的软件结构。  静态地看,计算机软件我们可以理解为一组文件(当然也可以是一个),这些文件可以相对独立的运行,帮我们完成某一项工作。一般来说,我们可以把这些文件分成几类:  1、可运行文件(exe或dll)。这是软件的核心,所谓软件开发,大部分工作就是制作这些可运行文件。  2、配置文件。用于描述软件的运行状态,一般数据量很小,但很关键。有三种常见的方式,ini文件、xml文件和系统注册表。  3、数据文件。软件本身携带的用于软件工作时使用的资料。可以是各种多媒体资料,也可以是数据库数据,形式最为多种多样。  4、用户文件。不是由软件事先携带,用户在使用软件过程中形成的文件。比较典型的是游戏软件中用户进度的存档文件,还有各种用户的定制信息。  静态的软件形体,就如同是没有生命的身体,对它的研究,多少会有一些软件维护方面的作用。但对软件开发来说,是远远不够的。至少我们得进一步研究软件的动态形体,也就生命体的行为规律。  而当软件运行的时候,各种静态文件被调入内存,一起完成各种具体工作,则似乎显得浑然一体。继续以静态的观点来看软件,对我们没有多少实际的帮助。这时,我们就应该了解其动态结构。对软件的动态结构的认识才是帮助我们理解软件和创造软件的关键关节。  就如同中医和西医对人体的运行模式有着不同的视角,不同对于软件的运行模式,也存在着许多不同的视角。基于不同的视角都可以进行软件开发,软件的运行时模式,我先介绍三种比较典型的整体模式。  第一种典型模式,是从汇编视角看软件的运行时模式。软件呈现为许多组相互协作的机器指令序列。指令序列保存于不同的内存空间段,软件所用的数据也保存于不同的内存空间段。为了方便寻找这些指令和数据,就把内存空间进行了地址编排。所以汇编语言发展了有许多不同的方法进行所谓的“寻址”工作。这种模式,我们知道就可以了,在软件开发过程中基本不会用到。  第二种典型模式,是标准窗口应用程序。软件就如同一台有着显示窗和各种按钮、控制杆的机器设备。按下不同的按钮,软件可以做出不同的响应,完成不同的工作。在软件内部,表现为事件驱动的模式,各种可能的对这台软件机器的操作,都被命名为事件,软件开发的过程就是写出各种事件的处理程序。  第三种典型模式,是网络软件。软件成为通过各种“超链接”联系在一起的一系列“页面”。有些页面用于展示内容,有些页面用于获取用户交互信息。软件的开发工作也就是设计和制作这些页面及其相互关联。
 
写的很好,顶一个。
 
路过,顶一下
 
又有一个病人,女人是让你爱的,不是让你研究的软件是来用的,不是让你研究的
 
3楼很强,软件=女人?
 
认识你自己,然后认识世界。 中医将人体看成一个和天地宇宙相似的一个复杂相关系统,西医试图从一些特征出发,将复杂系统分解为互不干扰的部分。 一阴一阳之谓道——半导体与布线、硬件与软件、算法与数据结构、程序与数据、逻辑与界面、对象与协作、服务与会话、节点与运算、引擎与脚本、架构与功能、稳定与进化。
 
好文,顶了.[8D]
 
无语。。。。。。。无病呻咛。。。。。
 
软件的魄  一般情况下,人们很少去区分魂与魄。所以我先简单介绍一下:“附形之灵为魄,附气之神为魂”。简单地说,魄相对比较重浊,是形体的直接控制者,但离开了形体,魄是无法存在的,与形同灭。魂则相对轻盈,可以轻松离开形体,但没有魄的辅助则无法控制形体。所谓的转世投胎的,只能而魂,而不是魄。例如我们在一些古代小说中看到某人的魂被带到地府打官司或者是魂游某地,他的身体就处于有魄无魂的状态,仅可以维持身体的正常机能。一般而言,我们所指的某个人,是指其魂而言,不过离开了魄,魂就失去了可以行动的身体,所以先研究魄的机制。  软件被载入内存后,形成了动态的软件,软件的行为是怎样的,怎样控制软件的各个部分,怎样控制计算机,都基于其运行时模式,深入种控制模式的细节,我们就看到了“魄”的存在。我们经常听到说人有三魂七魄,对于Delphi语言开发的软件来说,没有那么复杂。大约说起来只有三魄,一个是通过各种封装好控件直接控制软件和计算机的各个硬件;一个是直接通过系统的消息系统对计算机进行控制;还有一个是通过系统API直接进行系统操作。理论上来说,只通过后两种方式就可以完全实现计算机的控制;实际上来说,只通过第一种方式就可以很方便地实现计算机的大部分控制。后两种方式对计算机的控制,更加接近系统的底层,在各种语言中几乎通用。我只专论一下控件系统。  一个Delphi的运行程序,在Delphi中用一个全局的TApplication对象来代表,比如我们想访问运行程序的exe文件名,全局事件处理,在这里就是最方便的了。程序运行的桌面和显示器,在Delphi中用一个全局的TScreen对象来代表,通过它可以了解屏幕的分辨率,还可以支持多显示器。程序的窗口界面,是用多个TForm对象来代表。在窗口之中,每个可以看到的物件,包括文字(TLabel)、图片(TImage)、按钮(TButton)、输入框(TEdit)、单选框(TRadioButton)、复选框(TCheckBox),等等也都是由控件构成的。上面所说的TApplication,TScreen,TForm,TEdit等等都是控件。Delphi有一套控件体系,所有的控件的根,都是TComponet类,不可见的控件都从这里直接发展而来(例如:TApplication,TScreen);对于可见的控件,都经过一个TControl阶段,然后再从TControl发展为两个分支:TWinControl和TGraphicControl,其区别简单来说,TWinControl是借用了Windows的内部机制真实的控件(例如:TForm,TEdit),而TGraphicControl则是自行画上的(例如:TImage)。每个控件虽然管理的事物不同,但本质和事实上都是平等的。控件,包含三个内容:属性、方法、事件。属性是一个控件所有可设置的参数,比如尺寸、颜色等等;方法是一个控件所有可做之事;事件是一个控件的对外交互的接口,程序就是通过各种控件的事件来控制计算机的软件和硬件。事件本质上是一种特殊的属性,但由于其特殊地位,所以单独把它列出来。  总结一下,软件的魄提供了“怎样进行控制”的机制,但“进行怎样的控制”,则由软件的魂来决定。
 
软件的魂  软件的魂就是它的数据结构与算法。数据结构与算法又分为两个层面(二魂):逻辑结构和存储结构。逻辑结构是真正无形无态的,不能对任何具体事物施加影响;但存储结构则略有形态,可以通过其存储结构深入具体的软件开发语言,并通过软件的“魄”控制软件与计算机的各个局部。关于魂,人们一般所称的人,就是指魂而说的。同一个魂附于不同的身体上,我们通常习惯于称他为同一个人。软件也是一样的,同样的数据结构与算法,用不同的语言在不同的平台上来实现,我们也通常会认为它是同一个程序。哲学界经常讨论非物质的意识何以能够作用于物质,这里就给出了一个很好的解答。  所谓数据结构,实际上是对客观世界各种结构的抽象。大体上有这样四大类:集合、线型、树型、图型。这四类结构的特点是:集合结构的组成单位彼此之间必然的关联;线型结构的组成单位最多只有唯一的一个上级与一个下级;树型结构的组成单位最多只有唯一的一个上级,但可以有多个下级;图型结构的组成单位之间可以任何的关联方式。集合结构的典型例子就是关系数据库,一个表中的各条记录就是集合关系;线型结构的典型例子就是树祖、栈和队;树型结构的典型例子就是传统的文件目录系统,上级文件夹只有一个,下级可以有多个文件夹;图型结构则的典型例子就是我们访问的互联网,各个网页之间通过超链接可以各种方式互联。  所谓算法,可能最早是一个数学方面的术语,比如,辗转相除法是求最大公因数的一个高效算法。但在软件开发中现在用来代表解决任何问题的程序方法。比如,画直线的锯齿消除法,语音和图像的识别,这些可能是比较典型和复杂的算法;再比如,软件用户希望可以自行设定窗口布局,这仍是一个算法问题。  除了教科书那些被仔细研究过的典型问题(例如排序、搜索、背包问题等等),真正在软件开发中使用的大量算法没有那么典型,都是必须临机设计的算法,能够设计出来才是第一位的,对其效率的追求倒在其次。在许许多多的商业软件,你都会看到一些奇怪的功能实现,都是因为没有想到适当的实现方法,所以只好“通过管理手段来实现”,比比皆是。  至于算法效率,教科书上一提到算法就开始大讲,无非是空间复杂度和时间复杂度两个方面。诚然一个好的算法,应该速度尽量快,空间尽量节省。不过在实际应用中,算法优劣的实际指标应该是其直接性,一个直接的算法,即使效率稍低,也远远超过牵强的高效的算法,一个最大的原因就是直接的算法对需求的变动能够更好的适应。  怎样设计一个好的算法,才是软件的关键。算法设计的核心就是建模,只有把想表现的东西的内部逻辑彻底搞清楚了,才能设计出一个直接而高效的算法,并且经得起适当的需求变动。数学建模课程中讲了许多有价值的例子,不过这类课程中大多局限于数学感很强的算法,而在软件中使用的绝大多数算法都是非数学的。现在最好的算法设计的参考书就是比较流行的《分析模式》、《设计模式》等书,聚集了大量的前人经验和智慧。  所有的代码逻辑,不论多么复杂,都是用最基本的5个逻辑组织起来的。这五个基本是:赋值、顺序、分支、循环、函数调用。  赋值的本意是向某个内存地址中存储某个数字,程序中用一个字母来代表这个内存地址,称作变量。这一操作现在被赋予了非常多的新含义,可以说计算机软件开发的大多数奥秘都在这里。谈到变量,就不能不提一下变量类型。简单的变量类型包括整型、浮点型、字符串型,“面向对象的软件开发思想”则引入了大量的自定义类型,称作类。变量和变量类型的概念务必区分清楚:变量类型是一个抽象的概念,变量是一个具体概念,同一个变量类型可以定义许多变量(例如:var a, b: Integer;
Integer是整型变量类型,a, b是两个不同的变量)。在“面向对象的软件开发思想”中,对象就是变量的概念,类是变量类型的概念(例如:var edit1: TEdit;
TEdit是类,edit1是对象变量)。  顺序、分支、循环,是三个基本的逻辑流程。  函数调用是软件开发迈过复杂性门槛的最关键一步。通过大量自定义的函数封装了软件部件的复杂性细节,使主程序可以用能够掌控的复杂度实现强大的功能。拥有一个实用而丰富的自定义函数库,可以帮助经验丰富的软件工程师大大提高开发速度和可靠程度。另外一个关键点是函数调用提供了递归的可能,使一些算法可以简单地实现。
 
关注 标签
 
后退
顶部