软件开发中的“OO”到底是什么?真实案例解析OO理论与实践
一、导言
为什么要写这个系列
(资料图片仅供参考)
“OO都是一个已经被讨论烂的话题了,还有什么可写的!”
不知当你看到文章标题时,是不是有这种疑问,或者鄙夷。不错,OO从诞生到现在经历了不短的岁月,与其相关的理论、技术、原则、实践、模式、语言已经出了一大堆。可是,你真的了解OO的本质吗?真的能挥洒自如的将OO应用于软件开发中吗?真的能发挥OO的能量,从而提高软件质量吗?如果对这三个问题,你不能很干脆的点头说:“是的,当然!”那么也许你可以抽一点时间,往下看一看。
这个系列文章不打算大篇幅重述各种OO理论,也不打算谈各种OO心法。这系列文章着重于通过实践澄清一些对OO的误会,帮助朋友们更好的使用正确的方法将OO应用于实际开发中。同时,在必要的地方简要叙述一下OO相关知识。
所以,这个系列不是关于OO理论的天书或OO参考大全,而是告诉你“你对OO可能存在哪些误会与认识上的偏差”以及“如何走出误会更好的OO应用于实践”。
OO是技术,不是理论
OO,我认为全称应该叫做“面向对象技术”。其实,OO自诞生那天起其全部目的就是应用于软件开发实践中,提高软件开发质量。这也是OO存在的全部意义。所以,搞OO和搞数论、搞理论物理不一样,不能脱离应用。搞OO的人应该算是工程师,而不是科学家。两者最大的区别是:科学家可以不考虑自己研究的成果有没有什么应用价值。而工程师不一样,他们要更“势利”,要时刻关心自己研究出的东西有什么应用价值。所以一切OO的研究要以可应用性为向导,不能天马行空夸夸其谈。
当然,OO需要理论支撑,但是一定要是有现实意义的理论,而不能像数学家那样为了理论而研究理论,更不能将已有理论当做教条机械性使用。
因此,在学习和实践OO的过程中,要时刻注意和应用性联系起来,才能避免走入理论OO和教条OO的歧途。
到底什么是OO
“什么是OO?”对于这个问题,很难一言以蔽之。但正是由于对这个概念的误解和偏差,才使得某些朋友一直不能正确使用OO,不能让OO真正服务于软件开发,到最后开始怀疑OO、鄙视OO甚至唾弃OO。
在所有对OO的偏差性认识中,最普遍的一点就是“金锤”式理论,即“XX就是OO。”例如,“把所有东西看成对象就是OO”,“遵循封装、继承、多态就是OO”,“应用良好的OO原则进行设计就是OO”,“使用UML就是OO”。显然,这种“一锤子敲定”的方式会让人割裂的看问题,从而无法从全局角度正确把握OO。
在这里,我斗胆给OO下一个定义:OO,即面向对象技术,是一种旨在提高软件质量的综合性技术,其贯穿于软件系统的调研、分析、设计、开发、测试、维护、扩展、升级等整个生命周期,它包含一系列概念、思想、理论、目标、原则、实践、模式、工具、语言等要素,这些要素既相互区别又相互联系,同时从宏观和微观两个角度共同协作,指导和引导开发人员开发出高质量软件,并指导与开发有关的一切过程。
从上面可以看出,OO并不是孤立的概念或技术,而是一系列要素的复合体,并贯穿于整个软件开发周期。所以,仅仅从某个时间或控件切面切入而应用OO,这样的OO是不完整的,也不可能发挥出其应有的作用。打个比方:如果使用OO的方法和工具进行分析、设计,但是编码过程不能做到OO,就好比制造了一辆豪华的轿车却找头驴拉着走,是不能提高你出行效率的。反过来,如果你是一个C#或Java高手,但分析设计过程不遵循OO,直到编码时才用C#或Java试图OO,这无异于你听说开车能提高出行速度,于是你苦学驾驶技术,并掌握了高超的驾驶本领,但最终却坐在一头驴子上,于是你开始大喊:驾驶技术是骗人的!根本没法用!是啊,驴子上连方向盘、离合器都没有,空有一身驾驶本领又如何发挥出来呢。
这个系列的文章概要和内容组织
这系列文章的大体写作方式,是通过一个实际案例《XX食品公司连锁店在线定料系统》的调研、分析、设计、开发等一系列过程,帮助大家更好的认清OO如何实践,同时澄清一些误会。这个系统是我曾经参与过的实际案例,为了文章需要,将进行一定程度的修改,但一些很关键的东西都会原汁原味保留下来。在整个过程中,请各位不拘泥于具体技术相关问题,而要一直保持一个较高的视端,一睹OO的全貌。
文章的大概组织方式:
第一部分:需求分析之前的故事
很多人认为就软件开发来说,第一步是需求分析,其实非也。如果想更好实践OO,需求分析之前还有很多工作,如特性调研、降低风险等环节,这一部分我们讲讲需求分析之前的故事。
第二部分:分析步步高
这一部分开始对系统进行真正的分析,让我们来看看OO是如何引导和指导我们分析的。
第三部分:设计的方方面面
设计是一个繁杂的过程,诸多OO原则与模式都会应用于其中,这一部分不会细讲各种原则及模式,而是看看正确应用原则与模式的方式是怎么样的。
第四部分:让所有努力开花结果
这一部分,我们将前面的成果付诸实践。通过这一部分,可以清楚的看到前面做的一切工作都不是飘在云里的空中楼阁,而是开发高质量软件不可缺少的部分。
以上是目前的规划,当然,在整个过程中可能会出现变化,但是大体条理不会打乱。希望本系列文章能给您带来帮助。
二、第一项任务:特性列表
第一份说明
当这个项目开始时,我们得到的关于我们要做的系统的唯一说明是一页Word文档,这是一份简单的不能再简单的说明。文档里只有一行字:我们需要一个系统,使得全国各地的代理加盟商和连锁店能够通过网络订购原料。另外,我们还知道这是一个食品公司,主营面包、麻花、肉夹馍等食品,在全国各地有多家连锁机构。除此之外,我们一无所知。
永远不要和客户谈需求
软件开发的第一步是什么?很多人觉得是需求分析。显然这短短的一句说明无法满足我们的要求,于是很自然的,你希望找客户谈话,详细了解情况,然后做出详细的需求分析。于是,你心里有了这么一个算盘:
和客户谈话 -> 问清所有需求 -> 进行需求分析 -> 生成需求文档
乍看之下,这是很合理的步骤,但是实际上这是不可行的。原因有如下几点。
1.客户不关心系统的所有方面
每个开发人员都希望,客户可以清楚的把自己需要的东西的方方面面清楚无误告诉你,然而,这只是一厢情愿罢了。因为,任何一个客户在需要什么东西的时候,只会大致想想要个什么东西,并不会将所有地方都仔细想清楚。
2.有时客户并不清楚自己到底要什么东西
有时候,客户并不是很清楚自己想要什么。这不是天方夜谭。很多时候,客户仅仅有一个“想要实现某个目的的动机”,而没有“我需要一个什么系统”这么明确的概念。例如,从上文那个“一句话说明”中,可以看出,我们的客户仅仅是有一个动机:希望有一个系统,能使得他们公司的代理商和加盟店在线定料,至于这是一个什么样的系统,他们并没有明确的概念,更不用说这个系统有什么样具体的需求了。
基于以上两点,你是不可能从客户那里问清所有需求的。实际上,就不该和客户谈需求,因为需求从来就不是“客户面”的东西,而是“开发人员面”的东西。需求需要包含方方面面系统需要实现的功能,而客户往往并没有如此精细想过,甚至客户自己对自己想要的东西什么样子都不清晰。面对这种客户,你一本正经往他面前一坐,开发笔记本说:“我们谈谈需求吧”,或说“我们进行需求分析吧”,我想客户会立马崩溃,而你也不可能得到你想要的所有东西。
作为开发人员,不应该一开始就和客户谈需求,而要先谈特性。很多需求并不需要客户告诉你,开发人员应该能通过常识识别出来,就如没有哪一个买汽车的客户会说:我需要一个辆汽车,要有方向盘,还要有四个轮子。他们通常会说:“我要一辆家用车、要省油、舒适,要至少能坐3个人。”这“家用车”、“至少能坐三个人”就是特性。
特性是一些描述,一条特性简要描述了系统的一个客户最关心的核心功能。
最为开发人员,首要任务不是做需求分析,而是帮助用户整理出一份特性列表。这里之所以说“帮助”,是因为很多时候,客户由于自身太关注于某个方面,而漏掉了十分重要的特性,这是你要帮客户想想,并将想到的特性询问客户是否是需要的。如果客户很高兴的说“对!对!”,那么这就是大功一件。所以,在初期阶段,开发人员一定要想客户之所想,急客户之所急,尽快帮客户理清系统有什么特性。
所以,正确的过程应该是:
询问客户系统都有什么功能 -> 写出初期特性列表 -> 想想什么遗漏特性,并询问客户 -> 查漏补缺
生成特性列表
下面回到案例。
虽然客户的说明只有一句话,我们还是整理出一份初期的特性列表,并将其作为我们向客户展示的第一份工作成果。这份特性列表内容如下:
1.可以将各种原料信息发布到系统上
2.加盟商和连锁店可以通过系统在线定料
没错,我们的初期文档只有两项特性。我们把这个给客户看,客户说:“嗯……大约是这个东西吧。”很显然,我们的客户是比较懒的那种,这时,我们有义务引导客户想起更多需要的特性。下面是当时大约对话: 开发人员(简称D),客户(简称C) D:你这个加盟商和连锁店是要如何区分呢? C:我们公司有一个加盟商和连锁店的记录。 D:那么你们是准备将各个加盟商的信息全部录入系统吗? C:不是,我希望他们能自己注册,就和论坛那种。 D:那么你要如何确认他们的身份,总不能任何人都可以在这个系统注册吧。 C:嗯,我们公司有各个加盟商的详细信息,我们希望他们注册时提供足够的信息,我们进行核对。 (于是我们飞快写下一个特性:加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统。)D:你们得在后台能发布各种原料的信息吧。 C:嗯,使得。 D:这里有没有什么特别的要求。 C:没有吧…… D:好的,那么你们准备设立几个人负责管理这个系统。 C:就一个人吧,就信息部那个。我们就这一个比较懂计算机的。 D:也就是说不需要有多个人分别管理这个系统? C:不需要。 (写下一个特性:系统需要一个管理员,可以对系统进行管理) D:在你们的加盟商进行定料时,你希望他们怎么操作啊。 C:这个,我没仔细想过…… (看客户对这个地方比较不清晰,我们打开了一个网上书店的网站,给他演示了一下购物车购物的过程) D:你看,你的这个定料过程是不是和这个购物过程很相似,加盟商定料是不是就相当于从总公司购买原料啊。 C:对对!就要这种效果的! (这里要记住,在特性不能直接说清楚时,找相似事物是一个不错的选择。也就是说,说明这个特性像什么,不像什么) (我们又加一条特性:使用购物车功能进行网上定料) D:付钱这一块怎么弄,需要网上支付吗? C:不了,我们一般又财务专门做钱这一块工作。 D:那买完原料后要不要什么凭证呢? C:买完后生成一份定料单吧,打印出来,交给财务,财务清算款项,款到账后通知原料那边发货。 (又一条特性:定料完成后生成定料单,并可以打印) D:那么关于这些交易,你一定希望能查询吧,你希望怎么查询。 C:哦,这些我们财务那边有专门的财务软件。你这个系统只要能让加盟商定料就行了。
到这里谈话基本结束,我们得到如下一张补充过的特性列表: 1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以通过系统在线定料 3.加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.使用购物车功能进行网上定料 6.定料完成后生成定料单,并可以打印
我们将补充后的特性列表给客户看了看,基本得到了认可。
到了这里,我们第一步就差不多做完了。但是,我们还是不能马上进入需求分析,因为这之前还有很多事情要做。例如,特性整理,风险规避,这都是后面要讨论的话题。
重点总结 1.客户不会想到方方面面。 2.有时客户并不明确自己想要什么东西,而仅仅是有个动机。 3.不要和客户谈需求,要谈特性。 4.开发人员有义务引导和帮助客户挖掘系统的特性。 5.当客户描述不清某个特性时,可以采用找类似事物的方法,说说这个特性像什么,不像什么。 6.在软件开发初期,我们需要首先整理出一张特性列表,而不是做需求分析。
三、降低风险
风险无处不在
在上一篇文章中,我们写出了一张特性列表。然后是不是就可以做需求分析了?很遗憾,还不可以,我们仍有许多工作要做。拿到特性列表后第一件事,就是要尽量降低风险。这里先不长篇大论风险如何如何,我们先做,从做的过程中体会降低风险的涵义。
DRY
这里,首先要引入一个OO原则——DRY。
DRY原则,全称Don"t Repeat Yourself,指:在系统中,每一个信息或行为片段应该仅仅存在一份,且存在于合适的地方。
对于这个原则,很多朋友将其理解为“不要出现重复的代码”,这是很片面的理解。其实,OO本身并不是仅仅关于如何写出优秀的代码,而是关于如何开发出优秀的软件。所以,很多OO原则并不是仅仅代码层面的原则,而是可以应用于整个开发过程的。下面来着重看看这个原则的深层意义,以及讨论其在降低风险中的应用。
如何利用DRY降低风险
在所有的开发风险中,有一种风险,是由于同一个信息或行为片段分散于系统的不同地方,从而导致重复劳动,并且给修改和维护造成隐患。
下面,分别通过例子来描述两种不良后果。
1.重复劳动
例如,在特性列表中,如果两个特性本身应该是一个特性,但被误认为是两个不同特性。那么所有基于特性的分析和设计都存在重复劳动,即对同一个特性,做了两遍分析和设计,直到发现重复为止。这个代价是巨大的。
2.修改和维护隐患
例如某一代码段完全相似,但是出现在程序的诸多地方。这些相似的代码段一定是完成完全相同的功能,于是有着“同生同灭”的特点,即如果某段代码要修改,一般来说所有这段代码的重复代码都要修改。这就给维护带来很大隐患。
DRY原则正是针对这种风险的一个解决方案。关于DRY在代码中的应用,暂且放下,这里只看它在特性列表整理中的应用。显然,根据DRY原则,要求特性列表中的特性不能具有重复,那么我们再仔细看看我们的特性列表: 1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以通过系统在线定料 3.加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.使用购物车功能进行网上定料 6.定料完成后生成定料单,并可以打印
仔细检查,不难发现2和5其实是在描述一个特性,于是我们将2和5合并成一个新的特性:加盟商和连锁店可以使用购物车功能在线定料。另外,可以看出,“总店负责人”和“管理员”其实是一个概念。整理完后,得到如下新特性列表: 1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以使用购物车功能在线定料 3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.定料完成后生成定料单,并可以打印
再仔细检查,已经没有重复特性。这样,我们就应用DRY原则规避了第一种风险:重复劳动的风险。下面给这种风险下一个定义:
重复劳动风险——指由于重复特性的存在,导致对同一特性进行了一遍以上的分析设计过程。最终导致资源浪费,开发效率降低,可能导致无法按时交付。
知之为知之 不知为不知
在使用DRY整理完特性列表后,下一步就是要规避第二种风险:概念模糊。
概念模糊风险——指由于开发人员对于某一领域知识不熟悉,而将某一个概念想当然,继而根据这个想当然的结果进行分析设计。如果其想法错误,则会导致系统无法正常使用或无法完成业务既定目的,从而导致返工或项目失败。
很明显,一般来说开发人员并不是业务专家。所以对于领域业务不熟悉是很正常的,作为一个合格开发人员,应该谨遵孔老夫子“知之为知之,不知为不知”这一教诲,谨慎负责对待不熟悉的概念,而不能从字面臆想。正确的做法是,首先审视特性列表,对于不熟悉或拿不准的概念,去请教领域专家或客户。下面继续以我们的项目为例。
经过对特性列表的分析,我们找出以下疑问或模糊概念:
1.原料(都是什么原料,需要分类么?)
2.加盟商和连锁店(两者有什么区别?定料业务流程一样么?)
带着着两个疑问,我们再次拜访了客户。具体交谈就不说了,最后我们得到了如下结果。
1.原料主要就是些炸粉、调料之类的配方需要保密的烹饪原料,没有太特别的,不需分类。
2.加盟商和连锁店不是一个概念,加盟商直属总公司,连锁店可能直属总公司也可能直属某加盟商。加盟商和直属总公司的连锁店直接向总公司定料,不直属的的连锁店向相应加盟商领取原料。连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同。
经过以上一番了解,我们基本把模糊概念搞清楚了,并且经过这么一了解,我们的特性列表随之改变: 1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以使用购物车功能在线定料 3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.定料完成后生成定料单,并可以打印 6.直属连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同
我们认为加盟商级别和折扣是很重要的特性,于是把它加到了特性列表里。
保证我们能够实现
上面我们已经避免了两种风险。现在再来看一种风险。举个例子,如果一个建筑设计师,设计了一座新型别墅,其中有一条特性是:院子里有一个季节调节装置,可以随意将院子里的季节调节为春夏秋冬中任意一个季节。你们认为这个特性怎么样?很酷的创意对不对?但是如果你是别墅的客户,你会这么想?我想你不会和设计师一起为这个非常酷的特性而激动,你会首先问设计师要怎么实现这个功能。没错,可以调节季节的院子是很棒,可以不要忘了,最终我们的别墅是要建筑在实际中的,而实际总会有诸多约束不能让每一个想法变成现实。
同上。无论我们设计的东西多么天花乱坠,最终都是要编码实现的。所以,我们要保证所有的特性可以在编码层级上有解决方案。即使我们不能马上知道精确的解决方案,但也要大体知道怎么实现。由此引出了第三种风险:
实现能力风险——指由于某项特性不能由具体技术解决带来的风险。这种风险包括两个层面,第一是现有技术完全解决不了。第二是由于开发团队没有解决方案。这种风险可能导致项目延期甚至失败。
要规避这种风险,就要逐一审查我们的特性是否可以在现有技术范围内解决。仔细审查后,第一个层面应该是没有问题,所有这6种特性都可以在现有技术内解决。但是对于特性2,我们存在一定问题。因为当时我们都没有设计购物车的经验,一下子不知购物车是如何实现的。
为了解决这个问题,要做如下工作。这里要注意,我们在这里可能讨论了很多细节,但是我们要避免提前进入细节。所以,这里讨论的所有细节并不是要进行分析或设计,而仅仅是通过头脑风暴的方式大约有个谱。这个“谱”往往和最终的实现有很大不同,但是至少我们知道这个特性通过某种方式可以实现。
在遇到这种风险时,首先要做的是查找相关资料。在查找了一些资料后,我们了解到购物车一般分为Session实现方式和数据库实现方式。这两种方式特点不同,前者支持未登录购物,确不能保存客户购物信息。而后一种又必须登录后才能购物。这里涉及到客户的利益,所以要由客户决定。
于是,我们询问了客户,得到的答复是“未登录时要可以定料,而且也要保持定料信息。”这句话有点模糊,但大体可以知道客户的意思,于是我们改写成如下一段话“未登录的用户可以使用购物车,但不能下定料单,登录后才可下单。登录用户可以保持购物车中信息。”我们拿给客户看,并进行了一定描述,客户认同了这个决策。
这个确定后,我们就要讨论一下具体解决方案了。我在这里再次说明,以下的讨论不是分析或设计,而仅仅是让我们对棘手的问题更清晰一些,从而心里有个谱,避免实现的时候不知如何是好。
在经过一番讨论后,我们都同意的解决方案是“未登录的用户使用Session处理购物车,登录的使用数据库存储购物信息。当用户登录时,如果Session中有将购物信息,将Session中的信息转入数据库。”
这个讨论可以到此为止了。因为我们不需要太精确,我们只要大致心里有个谱就行了。
重点总结1.特性列表完成后,我们首先应该降低风险,而不是做分析或设计。 2.重复特性存在风险。可以用DRY原则处理。 3.存在模糊不清概念的特性存在风险。请仔细询问客户,不要想当然。 4.不知如何实现的特性存在风险。一定要保证对每条特性的实现方式心里大致有个谱,但不需很精确。
四、通览全局:避免过早陷入细节的泥沼
细节的泥沼
现在我们再次将特性列表贴过来: 1.可以将各种原料信息发布到系统上 2.加盟商和连锁店可以使用购物车功能在线定料 3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统 4.系统需要一个管理员,可以对系统进行管理 5.定料完成后生成定料单,并可以打印 6.直属连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同
我们已经和这则列表折腾很久了,相信很多朋友已经厌倦了,肯定在想:不要在折腾这该死的特性列表了,赶快开始吧。这点我同意。但是要开始做什么?很多朋友可能会说:开始用例分析吧。说实话,用例是好东西,它让我们清晰认识到系统的工作流程,正式因为过于清晰,所以很容易让我们陷入一个细节的泥沼。
应该说,从“特性列表”直接到“用例分析”不是一个好注意,因为特性列表关注于功能(Function),而用例关注于系统的业务流(Business Flow),我们从功能直接开始分析系统的细节业务流,这个跨越太大,不利于软件质量的保证。特性是相对分散独立的功能描述,而用例是系统细节,很明显,在这之间应该有一个过渡,而这个过渡,就是一个高层次的,从全局角度对系统的一个概观认识。这个概观认识起到承上启下的作用,既将特性列表映射为一个系统的大概模型,又给系统细节的分析奠定了基础。所以,在系统特性基本确定后,我们首先要从全局给出一个系统的概览,避免落入用例分析这样细节的泥沼。
概览系统的有力工具——用例图
既然我们要给出一个全局的系统概览,自然就需要有一种方式将其表达出来。显然,仅仅通过说是不理想的,我们需要一种能用于书面表达的工具,而这个工具,就是我们非常熟悉的UML图之一的用例图。
很多朋友可能有疑问,上面不是说不进行用例分析吗?怎么这里又画用例图了?因为用例和用例图表述的信息层面完全不同,用例更倾向于细节和业务流的描述,而用例图倾向于整体的描述。下面给出两种工具要表述的信息:
用例——表述某个交互操作的动作执行者、用例名称、具体流程过程、例外情况等。
用例图——表述系统有哪些执行者、有哪些用例以及执行者于用例、用例于用例之间的关系。
很明显,用例更关注于某一个操作的具体流程,所以适合在需求分析中使用;而用例图更关注于整个系统的使用和交互情况,因此能给我们一个系统的概览。
下面,我们就使用用例图,从高层次角度看看系统的样子。在这里还要说明的是,随着UML和用例分析技术的发展,提出了业务用例和系统用例的区别,而且用例存在不同的粒度。在进行高层次概览的时候,我们是使用的是一种粒度比较粗的用例图。也许在以后的需求分析中,我们还会使用粒度更细的用例图。
通过简要对特性列表的分析,可以画出一张如下的用例图:
可以看到,这个用例图并没有太多细节的东西,而仅仅描述了三个信息:1.系统有哪些用户 2.系统有哪些操作 3.系统和用户有哪些交互。这些,就是我们要的一个系统概观。
用例图的验证
画完用例图,我们并不是就完事了。因为,要使得用例图真的是全局概观,就一定要保证一点:图中用例覆盖了所有特性。如果不能覆盖所有特性,说明我们的用例图中缺少用例甚至缺少动作执行者。现在我们来验证一下: 特性1覆盖于“原料管理”。 特性2覆盖于“在线定料”。 特性3覆盖于“注册”和“加盟商和连锁店管理”。 特性4覆盖于“原料管理”和“加盟商和连锁店管理”。 特性5覆盖于“打印定料单”。 特性6覆盖于...???
我们忽然发现一点,这里并没有和折扣有关的东西,那么这个特性没有被用例覆盖。我们知道,如果要实现这个特性,系统中一定要有一定的折扣机制,而一定是有管理员设置的。于是我们增加一个“折扣管理”用例。注意,这里我们可以先不陷入细节,仅仅知道系统有这么一个折扣机制,至于具体怎么实现,到分析设计阶段再讨论。于是,修改后的用例图如下:
现在我们可以说:特性6覆盖于“折扣管理”和“在线定料”。
好了,这样我们已经确认,用例图的用例覆盖所有特性。
重点总结 1.不要过早陷入细节 2.在特性列表到用例分析之间,用该先有一个系统概览,让我们从高层次上审视系统全貌。 3.用例图是实现这种概览的有效方式。 4.用例不要粒度过细,要能反应系统粗粒度操作。 5.最后不要忘了检查图中用例是否覆盖了所有特性。
五、需求分析之前的故事
高质量软件的第一要素
到目前为止,我们做了很多工作,但是我一直在强调这些都还不是需求分析。在很多人心目中,软件开发的第一件事就是先做需求分析。那么我们为什么不这样做呢?这牵扯到一个关键的问题:我们都希望开发高质量的软件,而本系列文章的重点也是如何通过OO实践开发高质量软件,那么什么是高质量软件?
对于这个问题,也许很多人会说,是灵活的、是易于修改和扩展的、是可维护性高的、是用户体验好的、是文档完整的、是代码规范的、是性能处理优秀的……好吧,我承认,这些都是高质量软件必不可少的元素,但是,还有一个更重要的要素,就是:软件必须做客户希望它做的事。你的软件再灵活、编码再规范,客户不关心,客户最关心的是软件是不是完成了他期待的功能,可以做他希望软件做的事。所以,高质量软件的第一要素就是:让软件做客户希望它做的事。
知道了这点,就知道为什么第一步不是做需求分析了,因为需求分析的重点不是“让软件做客户希望它做的事”,而是“将需求分解归纳成开发人员容易进行领域分析和设计的信息片段”。所以,需求分析是开发人员面的东西,而不是客户面的东西。作为开发人员,我们要首先站在客户的角度看问题,而不能总是站在开发人员角度,和客户隔着一条河对话。我们要走过去,去河的另一岸。
回顾我们的工作
现在来总结一下我们目前所做的工作,你会发现,我们所做的全部工作,其目的就是让软件做客户希望它做的事。
我们首先总结出特性列表,然后通过分析和询问降低了风险,同时修改了特性列表,最后从做出一张用例图,使得从全局角度对系统进行一个概览。所有这一切,其实都是开发人员在“努力变成客户”,或说努力让自己站在客户的角度看系统,真正了解客户想让希望做什么。因为,最好的理解需求的方式就是理解客户想让系统做什么。
我们在哪里?看看地图吧
做了这么多工作,是不是有点迷失方向的感觉?似乎我们已经迷失在OO从林中,不知现在身在何处。好的,那我们看看“OO地图”吧,一方面搞清楚我们在什么地方,另一方面看看我们后续有哪些路要走。
以上就是实践中的大致开发流程。一般来说,开发大致分为两个阶段:前一阶段我们要站在用户角度,搞清用户想要系统做什么;后一阶段要回到开发人员角度,进行分析、设计、编码、测试等一系列操作。而我们现在正处在两个阶段的交界处。
一般在迭代阶段提倡使用迭代与增量的方式进行开发。至于这样有什么好处,以及OO如何于迭代增量方式结合这些问题,我们将在下一篇文章中结合我们的案例详细讨论。
重点总结1.高质量软件的第一要素是:软件做客户希望它做的事。 2.在开发初期,我们要尽量站在客户角度。 3.理解需求的最好方法是明白客户希望软件做什么。 4.开发流程大约分为两个阶段:搞清用户想要系统做什么和迭代开发。
六、迭代式开发与用例驱动
再次明晰开发流程
在上一篇文章“五、需求分析之前的故事”中,我给出了一幅开发流程图:
这幅图,加上前几篇文章的内容,给不少朋友留下诸多困惑。如“特性列表不算需求分析吗?”、“用例图怎么跑到需求分析前面去了?没有需求分析哪来的用例图?”为了解开这些困惑,我们应该先把开发流程各个相关概念给明确了。
在一般开发流程中,直观上可以分为两个部分:业务阶段和系统阶段。明确这一点非常重要。其中业务阶段主要进行的工作是与计算机无关的,而系统阶段才是和计算机相关的东西。上图中“我们在这里”那道竖线所指的地方,就是业务阶段和系统阶段的分界点。
而如果从建模角度分析,整个开发流程分为四个子流程: a)业务建模流程 b)系统建模流程 c)分析设计建模流程 d)部署实施建模流程 其中a)属于业务阶段,而b)c)d)均属于系统阶段。
业务建模流程的任务就是做业务分析、降低风险和给出系统总体概览模型。系统建模主要就是需求工程。分析设计建模就是我们熟悉的概要设计和详细设计。而部署实施建模是对系统的具体实施建立模型。
其中,我们一般所说的“需求”,实际是指“系统需求”,是在b)阶段进行的,所以a)阶段的一切工作,都不能算是需求分析。(当然,如果加一个前缀,说是“业务需求分析”,也是可以的,但是一般在软件工程领域,说“需求分析”是特指“系统需求分析”。)
而关于用例图的疑惑,大家应该知道,用例图分为业务用例图和系统用例图,而业务用例图产生于a)流程,这样它们当然会出现在b)流程,也就是需求分析之前。当然,在b)流程中还会出现用例图,这时就是系统用例图了。
明白了以上开发流程,我想很多疑惑就自然解开了。所以,其实我们所谓的“需求分析之前的故事”,就是业务建模流程。
系统阶段的法宝1:迭代与增量
在上文中,我们提到软件过程大体分为业务阶段是系统阶段。在前面几篇文章中,我们已经基本完成业务阶段,下面是进入系统阶段了。不过莫急,在正式进入系统阶段之前,我们有几个重要的、关于系统阶段的话题要聊一下。
如果你问我,在系统阶段最应该被牢记的是什么,我会告诉你,是两个词:迭代&增量。
我们已经知道,系统阶段是在业务阶段的基础上,在计算机领域内进行需求分析、系统分析、概要设计、详细设计、编码、测试、部署实施等一系列环节。但是,如果你想仅施行一遍这个流程,而完成整个系统的话,不好意思,你大致会精神崩溃。
如果这个过程仅实施一遍,其实就成了瀑布模型。小系统也许可以,但是稍大点的系统,将会带来严重的后果。我们知道,“软件开发中永远不变的就是变化”,如果采用瀑布模型,反馈将会非常靠后,一直要到部署实施阶段才能看到成果,如果客户要求更改需求或认为当前系统不是他们想要的,那么修改过程会异常惨烈,代价也是巨大的。
那么,我们应该如何实施系统阶段开发呢?法宝就是迭代和增量。具体做法是:
我们将整个系统分为许多相对独立的“单元”,每次只对一个或少数几个单元实施需求分析、系统分析、概要设计、详细设计、编码、测试、部署实施等一系列过程,一次这样的过程叫做一次迭代,而将一次迭代的成果加入现有成果的过程就叫做增量。
这种开发流程的优势是明显的:我们总是能在相对较短的时间内,完成整个系统功能的一个“子集”,这个子集是可以运行的,可以看到效果,所以如果用户不满意,反馈是及时的,修改代价也较小。通过合理的过程控制,变更代价总可以控制在一个可以接受的范围内。
在实施迭代&增量过程时,要注意一下两点:
1)迭代单元不是环节,而是系统功能的某个子集。如不能说第一次迭代完成需求分析、第二次迭代完成设计……这不叫迭代式开发,这叫里程碑式开发,和迭代有本质区别。
2)每次迭代一定要完整完成需求分析、系统分析、概要设计、详细设计、编码、测试、部署实施这一套环节,产生的成果必须是成品,是可运行、可交付的,是整个系统的一个子集,而不能是一个半成品。
系统阶段的法宝2:用例驱动
相信,大家或多或少听说过“用例驱动”。那么什么是用例驱动呢?如果你理解了上文的迭代&增量过程,就很好理解用例驱动了。上文不是说过,迭代时每次选取一个或少数几个“单元”吗?那么这个“单元”是什么?理论上,什么都可以,只要是对系统合理的划分。但在实践中,人们发现,使用业务用例作为迭代单元是最合适的。为什么呢? 其一,业务用例大小适中,规模平均。 其二,业务用例大多相互独立性好,适合进行迭代。 其三,业务用例能很好反映系统的功能单元。
所以,所谓的用例驱动就是以业务用例作为迭代单元进行迭代开发的流程。
你看,我们前面做了那么多业务分析,其中成果之一就是业务用例图。而这里,业务用例成了我们进行系统迭代开发的单元和驱动者,所以,软件开发过程不是割裂的,而是相互联系的,不会说上一个阶段过去就过去了,和下一阶段毫无联系。一般,上一阶段的产品总会成为下一阶段的材料。
在这里附上一副我自己画的示意图,希望能帮助大家理解本文内容:
本文理论讲得多了点,有点枯燥,但是必须讲,因为明白这些是以后进行系统阶段的基础。从下一篇开始,我们回归示例,进入真正的系统阶段了。下一篇,将开始第一轮迭代的起始阶段:需求分析。
重点总结 1.软件过程大致可分为业务阶段和系统阶段。 2.业务阶段进行业务建模流程,与计算机领域无关;系统阶段进行系统建模、分析设计建模和部署建模阶段,与计算机相关。 3.系统阶段的两大法宝:迭代式开发与用例驱动。
七、【第一轮迭代】需求分析与领域分析
在前面,我们花了六篇文章的篇幅去讨论需求分析之前发生的事情,这些内容看起来枯燥或飘渺,但实际是为真正开始系统的分析、设计和实现进行的必要准备。从这篇开始,将正式进入系统的开发阶段。这一篇文章,将讨论第一轮迭代过程中的需求分析和领域分析环节。
选取第一轮迭代要实现的特性
回顾前面章节,我们说到,“迭代与增量”和“用例驱动”是系统开发的两大法宝。另外,指出了如下几个要点:
1)迭代单元不是环节,而是系统功能的某个子集。如不能说第一次迭代完成需求分析、第二次迭代完成设计……这不叫迭代式开发,这叫里程碑式开发,和迭代有本质区别。
2)每次迭代一定要完整完成需求分析、系统分析、概要设计、详细设计、编码、测试、部署实施这一套环节,产生的成果必须是成品,是可运行、可交付的,是整个系统的一个子集,而不能是一个半成品。
所以,说白了,这第一步就是要从前面得到的特性列表或业务用例分析文档中选取一个或几个特性或业务用例进行实现。(因为特性和业务用例有对等映射关系,所以,从特性列表或业务用例分析文档中选取迭代功能点在理论上是等价的。)这里,我们从特性列表选取特性。那么首先把我们前面完成的特性列表再搬出来:
上图就是我们前面得出的特性列表,总共有六个特性。理论上,第一轮选取哪些,总共选取几个,没有明确的规定,但是,在选取特性方面,还是有一定经验可以遵循的,大致有如下原则:
1)就选取个数来说,与迭代周期有关。一般的迭代开发中,一个迭代周期大多选在一周到两周之间,不宜多于两周,所以,每个周期选择的特性要估算能在这个周期内完成。(顺便说一下,在每个周期内,如果发现时间不够,做不完计划,应削减一些特性推入下个周期,切不可延长周期。另外,切不可在周期开始后添加任务。)
2)就选取的特性来说,最好是比较内聚的几个特性。也就是说,每个周期选取的特性,要尽量关联紧密,而和其他周期的特性要尽量耦合度低。
3)就选取顺序来说,因为要求每一个周期都要产生一个可运行的子集系统,所以,最好先选取平台性、基础性、对外依赖弱的特性,再选取功能性、对外依赖强的特性。例如,在这个例子中,如果第一轮迭代选择特性2则不是一个好主意。因为购物车功能要依赖于管理员、加盟商、物料等诸多特性,在后者没有实现之前,很难单独做出一个可运行的购物车子集系统。
针对以上原则进行考虑,笔者最终选择3、4和6作为第一轮迭代的特性。
至于为什么这样选,我就不再分析,请各位结合我上面提到的三个原则自己思考一下。
领域分析
在确定迭代特性后,下一步要进行领域分析。领域分析就是针对特性涉及到的实体及实体间的关系进行一个分析,构造出静态领域模型。这里要注意三点:1、领域模型是静态模型;2、领域模型要反映的是实体及实体见得静态关系(例如包含等,而调用这类动态关系不该在这里出现);3、领域模型是比较高视角的模型,其中的实体和最终程序中的实体类未必对应。
领域分析的方法有很多,下面我使用一种我总结的领域分析方法。流程如下:
step1、提取特性中的名词
我们这个迭代周期内涉及的特性是3、4和6,从中可提取出如下名词:加盟商,连锁店,网络,管理员,系统,直属连锁店,原价,等级,折扣。注意,这些名词就是领域实体的候选者。
step2、筛选名词,确定实体
不是所有候选名词都是领域中的实体,这一步要对候选者进行筛选。这一步非常重要,也相对难度较高,需要结合经验和前面的客户谈论材料、需求记录等,必要时,要咨询客户或业务专家。下面我们进行筛选。
首先,“网络”显然不是领域内的实体,排除。“系统”是对整个产品的总称,也比较明显不是领域实体,排除。排除了两个明显的“干扰项”,下面看几个可疑的家伙,这里,我发现“原价”、“等级”和“折扣”比较可疑。通过对前面材料的回顾分析,基本可以肯定“原价”应为物料的一个属性,难以成为单独的实体,排除。而“折扣”和“等级”是否能成为实体,依赖于后续系统的设计方式,如果将等级单独设计成一个模块,则其应该为一个实体,而若将其设计为加盟商的属性,则不能成为实体。对于这种摸棱两可的候选项,我们姑且保留,并加一个“?”作为后缀。当然,由于前面分析中说明“折扣关联与等级”,所以,仅保留“等级”就可以了,“折扣”可作为其属性。
经过上述筛选,获得下列领域实体:加盟商,连锁店,管理员,直属连锁店,等级?。
我们不妨先将各个实体画入领域分析图。
step3、确定实体间的关系
有了实体,下面要确定各个实体间的关系。如上图所示,管理员比较容易确定,因为它似乎不与任何实体存在静态关系。这里比较纠结的是加盟商、连锁店、直属连锁店和等级四个实体。关于它们间的关系我们不能臆想,要去查阅前面的记录资料或去咨询客户。在OOA&D实践之路——真实案例解析OO理论与实践(三、降低风险)一文中,我们记录了这样一段文字:
“加盟商和连锁店不是一个概念,加盟商直属总公司,连锁店可能直属总公司也可能直属某加盟商。加盟商和直属总公司的连锁店直接向总公司定料,不直属的的连锁店向相应加盟商领取原料。连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同。”
从以上文字中,我们提炼出如下关系:
1)加盟商和连锁店没有关系。
2)直属连锁店是连锁店的一种特例。而且应该还有种“非直属连锁店”
3)非直属连锁店可能会属于某个加盟商。
4)等级仅属于加盟商。
到这里为止,几个实体间的关系基本清晰了,我们将其表达在领域分析图里:
以上就是第一轮迭代的领域分析图了。其中直属连锁店和非直属连锁店都继承于连锁店,而非直属连锁店必定对应一个加盟商,加盟商可以对应零到多个非直属连锁店,每个加盟商有且只有一个对应的等级。
step4、领域分析的优化
别觉得完成上述步骤就万事大吉了,虽然我们的领域分析模型已经出来了,但它可靠吗?还有优化的余地吗?万事多思考一点,总是没坏处的。就像刚出厂没经过检测的飞机,你敢坐吗?所以,这里我们要对已经成型的领域分析模型进行一个检测。检测的方法很简单,就是回顾前述工作,逐个点进行验证和确认。当我回顾了特性及初步业务需求后,发现如下两点问题:
第一、管理员是否是领域中的实体?要知道,领域中的实体,一定是系统边界内的实体。那这里就要分情况讨论了,如果系统只需要一个管理员,那么系统中就没有对管理员的管理,那么管理员只是系统外部的用户,就不能存在于领域实体中了;如果有多个管理员,并且管理员管理单独成为一个模块,则管理员应放在这里。于是我联系了客户,在确认系统只需要一个管理员后,我毫不犹豫将管理员从领域模型中抹去了。
第二、我觉得领域模型抽象层次还有所欠缺。加盟商和连锁店性质很类似,都有注册、都要被审核,其实它们应该继承自某个更高抽象,这里我称其为会员。于是经过思考和修正,得到最终的领域模型如下:
这里要注意,领域模型只表示出实体和实体间的静态关系就好了。至于各个实体有哪些属性,有哪些交互,那是后面设计阶段的工作。
基于用例的需求分析——编写用例图及用例规约
传统的软件工程中,通常使用需求规格说明书进行系统需求分析。而我更喜欢使用用例分析技术。在用例分析阶段,我们要输出两份文档:用例图和用例规约。用例图用于概观上描述需求,用例规约用于对用例的流程进行详细描述,直接作为后续设计、编码及测试的依据。
下面进行系统需求分析。
step1、提取特性中的动词
上面我们曾使用提取名词法找实体,那么要找用例,就要分析特性中的动词了。废话不多说,我们先提取出特性3、4和6中的动词:注册,审核,使用,管理,定料。因为用例分析中要确定每个用例的Actor,所以,在提取完动词后,要对每个动词赋予其主语,作为其Actor,于是,最终得到的提取列表如下:注册【未注册加盟商和连锁店】,审核【管理员】,使用【注册后的加盟商和连锁店】,管理【管理员】,定料【注册后的加盟商和连锁店】。
step2、动词筛选
同样的,不是每个动词都是合法的用例,这里也要对候选动词进行筛选。具体到这里,“使用”是个很泛的名词,不应该成为用例,而“定料”虽是用例,但于这轮迭代的内聚性不高,建议放入后续迭代中。最后得到用例:注册【未注册加盟商和连锁店】,审核【管理员】,管理【管理员】 。
step3、用例分析与优化
这里的用例有进一步分析的余地,首先,“管理”这个用例粒度太大,很难知道设计和开发,于是应进行分解;其次,“审核”应属于管理的一部分。基于以上两点,将管理分解为“删除会员”、“指定加盟商等级”和“审核会员”,另外,“未注册的加盟商和连锁店”,跟据领域分析,可写作“未注册会员”。另外,这里有几个隐含的用例,就是关于等级的管理,这几个用例从动词分析中是提取不出来了,这取决于特性描述的局限性。我们通过经验和个人的分析,得到关于等级的管理用例。于是,最终用例敲定如下(这里用例命名规则为 uc迭代周期编号.用例编号):
uc1.1 - 注册 actor:未注册会员
uc1.2 - 删除会员 actor:管理员
uc1.3 - 指定加盟商等级 actor:管理员
uc1.4 - 审核会员 actor:管理员
uc1.5 - 添加等级 actor:管理员
uc1.6 - 删除等级 actor:管理员
uc1.7 - 等级信息维护 actor:管理员
step4、给出用例图
跟据上述分析,给出用例图如下:
step4、编写用例规约
需求分析的最后一步,就是为每个用例编写相应的用例规约。用例规约是一种规范化文档,它面向设计开发人员,详细描述了各个用例内部的基本信息、执行流程及例外流程等,必要时可附上相应的活动图。因为用例规约是设计和开发的重要参考文档,所以在编写过程中务必要做到详尽和准确。
下面仅给出“注册”这个用例的用例规约作为示例和参考。
必要时,可在下端附上活动图:
总结
在每个迭代周期的初始阶段,当选择完需要迭代的特性后,就可以开始领域分析和需求分析了。本文是先进行领域分析。其实两者并无确定的先后顺序,往往是相辅相成,交叉进行。下一篇文章将进入第一迭代周期的设计阶段。
作者:T2噬菌体 出处:http://leoo2sk.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
标签:
相关推荐:
精彩放送:
- []环球快播:免费下载国外视频的网站 你值得拥有
- []【聚看点】华容道有哪些通关技巧?15数字华容道解法
- []泥巴潭:《新龙族》免费卷土重来 拒绝“菜鸟玩家”
- []世界观速讯丨速读2023年北京市政府工作报告 | 2023年北京将筹建保障性租赁住房8万套,竣工各类保障性住房9万套
- []每日热讯!泸州老窖:公司销售工作按计划顺利推进
- []北京:过去5年,建设筹集各类政策性住房54万套
- []环球看点!贵州石阡 中国最古老温泉的旅游热度如何继续升温?|新春里的中国经济
- []今亮点!* 中创新航遭摩根大通减持超5%,持股比例降至1.78%
- []【焦点热闻】海南瑞泽:截至2023年1月20日,公司股东人数为66,155
- []【BT金融分析师】比亚迪电动车市场份额持续扩大,分析师称其增长超过特斯拉
- []全球视讯!白求恩大夫是哪国人?诺尔曼·白求恩资料介绍
- []全球热消息:货郎是什么意思?现在的货郎指的是什么?
- []孤城闭帝后结局怎么样?孤城闭剧情介绍
- []【世界聚看点】苹果手机怎么打开微信深色模式?苹果手机打开微信深色模式的步骤
- []陕西的简称是什么?陕西省资料介绍
- []屈原历史资料介绍?对屈原的人物评价怎么写?
- []【独家】猎狐电视剧胡军演谁?猎狐剧情介绍
- []【独家】愚人节怎么发朋友圈?愚人节适合发朋友圈的搞笑说说有哪些?
- []全球观点:华为手机nfc是什么意思?近场通信的技术原理是什么?
- []每日热点:去哪儿2023春节报告:平均每个旅客多走400公里,出境机票同比增长6.7倍
- []天天日报丨这个春节,旅游人信心又来了
- []世界最资讯丨春运返程迎来客流高峰,有人坐绿皮火车返岗开工
- []“零下53度”的东北游,能火多久?
- []简讯:租赁模式的住宿业:合作、匹配、把控
- []全球今头条!我,过年不回家,“和9个陌生人去旅游”
- []【速看料】地产律师的一年| 飞了10多个城市,为购房者追回千万损失
- []天天热推荐:地产营销人的一年| 要时刻保证自己不被淘汰,“还没想过离开房地产行业”
- []今日热门!致远新能:截止2023年1月20日股东人数为11966人
- []热资讯!物业人的一年| 经历了疫情和高温考验,“我们圆满完成年度KPI考核”
- []产业策划人的一年| 产业板块被集团地产业务拖累,“相信今年会比去年好”
- []豪宅中介的一年| 在单价屡破30万元/平的区域卖房是一种什么体验?
- []蓝盾光电:公司将严格按照信息披露的相关规定,及时履行信息披露义务
- []环球快讯:132亿!宁德时代工厂投产!
- []【环球新视野】防城港各大景区人气爆棚
- []全球今日报丨国泰君安证券:美国经济外强中干 核心GDP继续回落
- []【环球新视野】马亮:扎堆式旅游何时休?游客要理性,景区更应强化能力建设
- []总投资53亿元!20万吨负极材料项目落地
- []世界实时:【首席展望】海通证券余文心:医药板块有望反转 看好三条主线
- []244亿!特斯拉又投两工厂
- []焦点快看:白酒“霸屏”春节假期 开门红迎新增长周期 今年收益或超额
- []环球观焦点:宁德时代牵头!斥资67亿元 开发玻利维亚锂资源
- []全球热文:中海董事长颜建国拜会香港特首李家超 积极参与北部都会区和明日大屿建设
- []渣打预测布油有望反弹至90美元以上,但对突破100美元并不乐观!
- []每日视讯:现货黄金交易策略:金价见顶风险增加,关注美国PCE数据
- []文化和旅游部:春节假期国内旅游出游3.08亿人次 同比增长23.1%
- []快讯:香港财政司司长:未有定案是否再派消费券 楼市现时有秩序调整
- []美国12月新屋销售量连续第三个月上升 同比仍降26.6%
- []天天观焦点:CFTC商品持仓解读:投机者提高美国原油净多头头寸
- []新春走基层丨保障多地轨道交通正常运行,众合科技员工誓要站好春节最后一班岗
- []广西出台16条措施 加快文化旅游业全面恢复振兴
- []环球即时:1月28日财经早餐:黄金连续第六周周线上涨,焦点转向美联储
- []速读:美原油交易策略:美国GDP数据缓解需求担忧,油价将重拾涨势?
- []热门:美股异动 | 移动金融智选平台简普科技(JT.US)涨超9% 年初至今累涨超31%
- []环球快播:美股异动 | 途牛(TOUR.US)涨超9.5% 年初至今累涨近67%
- []最新资讯:威海广泰:公司以技术创新为龙头,始终重视消防救援装备的技术研发工作,每年都有10余型新产品完成开发
- []环球即时:奥维通信:具体内容请详见公司于2023年1月20日披露的《关于终止筹划重大资产重组的公告》
- []新春行业动态合集 | 日媒:春节中国旅客访日需求依旧低迷;国航回应“一航班颠簸下坠”
- []当前快报:查询车辆保险怎么查询
- []全球快消息!手工钥匙扣制作图片_手工钥匙扣制作过程
- []【世界报资讯】文化和旅游部:今年春节国内出游人次恢复至疫前同期88.6%
- []旅游强劲复苏:多地游客数追平2019年,部分已反超
- []近3.08亿人次出游,收入3758.43亿元, 春节假期各OTA数据战报PK
- []世界快看点丨上万只基金产品 2000余位基金经理 兔年养基如何选?
- []携程2023春节旅游报告:旅游订单同比增长超4倍,其中出境游增长640%
- []状态火热!欧文三分球4中3半场独砍18分
- []钠电池元年将至 产业化到哪一步了?
- []快播:特斯拉杀疯了 价格还能降?美国重磅数据公布 传递什么信号?
- []当前动态:报价上涨12%,西藏山南光伏增配储能EPC中标公示发布
- []峰谷电价差扩大,低价谷电储热采暖优势明显
- []快讯:宝马计划量产全固态电池,最快2025年实现装车
- []今日视点:重磅发声!兔年怎么投?多家公募巨头最新研判
- []环球百事通!机构展望2023:中国市场更具吸引力 多元化投资组合提供机会
- []天天热点评!盘点︱2023年即将上市IPO光伏公司统计表
- []立冬的优美诗词句子_立冬的优美诗词
- []【世界聚看点】平安福7000交了5年能退多少,保单现金价值
- []世界速递!被银行忽悠买了保险可以退吗,可以退
- []热点聚焦:公积金能不能每月还商贷,当然可以
- []全球微动态丨最低-1℃郴州未来几天将迎霜冻天气
- []【环球速看料】兔年港股开门红!恒生指数涨逾2% 科技指数大涨超4%!多板块集体爆发
- []扩张性财政政策包括哪些(扩张性货币政策包括哪些)
- []天天简讯:为什么美金汇率一直在跌(最近美元汇率为什么一直在跌 最近美元汇率为啥一直在)
- []解析基金“专业买手”!FOF基金经理为何喜欢低换手?还有哪些特征?
- []农村信用社贷款无力偿还怎么办理(农村信用社贷款10万还不上怎么办)
- []基金gp和lp的区别优先和劣后(基金gp和lp的区别优先和劣后)
- []发力定制化场景金融布局 钱小乐探索精准营销新模式
- []最低或8万/吨!硅料价格拐点何时来临?
- []当前信息:微信转账退回对方会收到提示吗?(别人微信转账给我我退回有记录吗)
- []宏观经济分析包括哪些内容(宏观经济分析包括哪些内容)
- []今日聚焦!工商宝贝成长卡好不好(工行宝贝成长卡有什么弊端)
- []农业银行怎么查询冻结原因(怎样判断是永久冻结还是临时冻结)
- []全球今亮点!公积金4万可贷款多少(公积金账户4w可以贷款多少)
- []全球今亮点!地方债谁在买(地方专项债谁来买单)
- []天天热讯:京郊民宿老板:过完最冷清的春节,盼春暖花开不愁客人
- []焦点快报!携程:兔年春节过半,香港、澳门领跑春节出境热门目的地
- []天天最资讯丨春节楼市不打烊,部分楼盘推“0月供”计划,有客户打飞的到佛山买房
- []日元计价的黄金周三创新高,美元计价的或将紧随其后!
- []【全球新视野】中信证券交易手续费是多少(中信交易手续费)
- []环球观热点:明星税收怎么收费比例(明星的收入税率是多少)
- []杜邦奖学金_关于杜邦奖学金简述
- []热讯:港元1个月拆息四连跌 报2.94345
- B站注册资本增幅400%至5亿 目前由陈睿全资持股
- 光源资本出任独家财务顾问 沐曦集成电路10亿元A轮融资宣告完成
- 巨轮智能2021年上半年营收11.24亿元 期内研发费用投入增长19.05%
- 红枣期货尾盘拉升大涨近6% 目前红枣市场总库存约30万吨
- 嘉银金科发布2021年Q2财报 期内净利润达1.27亿元同比增长208%
- 成都银行2021上半年净利33.89亿元 期内实现营收同比增长17.27亿元
- 汽车之家发布2021年第二季度业绩 期内新能源汽车品牌收入增长238%
- 中信银行上半年实现净利润290.31亿元 期末不良贷款余额706.82亿元
- 光伏概念掀起涨停潮交易价格创新高 全天成交额达1.29亿元
- 上半年生物药大增45% 关键财务指标好转营收账款持续下降
- 世界今热点:宣发“重大失误”!邓超新片紧急撤档,上映首日票房、上座率倒数第一;春节档票房已超50亿
- 环球微资讯!多家光伏逆变器上市公司2022年业绩预喜 储能正成为重要增长点
- 年终:2022跨界储能企业一览表
- 头条焦点:投资600亿!比亚迪合作伙伴造电池!
- 山东和山西为何成为储能引领者
- 消息!碳酸锂涨价?再度直逼50万大关!
- 资讯:港交所兔年首个交易日 财政司司长陈茂波冀股市吐气扬眉
- 专题回顾 | 房地产企业并购融资现状解析
- 报告:今年房企主要“保交付”,销售和投资规模呈前低后高走势
- 天天热资讯!红星美凯龙:行使换股权后 阿里巴巴持有公司权益已达到9.99%
- 盘后机构策略:市场维持强势格局 关注春节后内资流入情况
- 以岭药业:奋力推进新时代中医药传承创新发展
- 当前要闻:五矿地产(00230)首季度合约销售额30.7亿元 同比下跌30.7%
- 热讯:已签收的电子汇票在哪里查询 在哪里查询已签收的电子(已签收的电子汇票在哪里查询 在哪里查询已签收的电子)
- 当前报道:股票分红在什么时间(股票分红多长时间到账)
- 覆铜板是什么东西及用途(覆铜板是什么东西及用途)
- 环球视讯!全部资本化比率公式(全部资本化比率公式)
- 小规模纳税人收到专票的风险(小规模收到13%的专票有风险没)
- 【天天速看料】按单利计算是什么意思 什么是按单利计算(按单利计算是什么意思 什么是按单利计算)
- 热点聚焦:利润率的公式怎么算的(利润和利润率的计算公式)
- 世界今头条!春节假期海南离岛免税购物“南北两旺”
- 当前要闻:什么叫收现比(收现比是什么意思)
- 热资讯!税金贷款有什么银行做(什么银行有税金贷)
- 速看:集中趋势指标包括哪些方面(集中趋势指标包括哪些方面)
- 天天播报:大学生可以开佳物分期吗(佳物分期大学生能用吗 大学生可不可以用佳物分期)
- 央行100亿逆回购是什么意思(央行100亿逆回购意味着什么)
- 环球速读:大年初四,怎么做能接好运?
- 新资讯:货币资金包括哪三项(货币资金包括哪三个部分)
- 当前播报:强赎触发价什么意思?(强赎触发价什么意思科普)
- 当前资讯!银行卡信息不完善是怎么回事(银行提示此卡状态异常)
- 无卡是否可以存款(不带卡可以存款吗)
- 全球播报:转账二十四小时没到账怎么办(跨行转账4天了还没到账)
- 【环球时快讯】红字冲销什么意思(红字冲销什么意思)
- 2022年房贷利率是降还是升(银行利率表2022最新住房贷款利率,房贷利率每年都会变吗)
- 【速看料】林木不动产权证可以贷款吗(没有林权证可以去银行贷款吗)
- 环球时讯:广发为什么叫废行(存钱要小心五家银行)
- 天天观点:监管账户什么意思(监管账户怎么查)
- 世界简讯:来分期上征信吗2021年(来分期上征信吗2022年,上征信)
- 公积金余额只有几千块可以贷款啊(公积金只有几千块可以贷款吗 公积金余额只有几千块能贷款吗)
- 全球今头条!去银行打征信报告需要带什么资料(去银行办个人征信需准备什么材料)
- 全球速读:怎么在app申请房产退税(怎么在app里办理房贷退税)
- 瑞信:维持PACCAR(PCAR.US)中性评级
- 全球快消息!金融中bps是什么意思(bps金融专业术语)
- 分付微信怎么开通 微信分付如何开通(分付微信怎么开通 微信分付如何开通)
- 火车退票手续费 火车票退票的手续费(火车票退票要手续费吗)
- 建设银行如何提高每日转账额度(建设银行怎么提高每日转账额度 建设银行转账额度怎么提升)
- 环球热消息:炒股票新手入门基础知识(炒股入门基础知识 新手炒股基础知识)
- 每日动态!如何查询自己的征信情况(如何查自己的征信记录是否有贷款)
- 快播:NYMEX原油下看79.03美元
- 支付密码忘了怎么办(手机支付密码忘记怎么办)
- 当前快看:台湾用的货币是什么币(台湾钱币叫什么名字)
- 国际金价短线或下测1920美元
- 延期到账怎么关闭(微信延时到账怎么解除)
- 焦点日报:举牌是什么意思?(什么是举牌)
- 每日时讯!mtn是什么币(mtn是什么币)
- 2021年车险优惠政策(车险优惠政策2021 2021车险优惠)
- 春节假期过半,昆明民宿预订量同比增长731%
- 天天讯息:中国银行被冻结只能进不能出(中国银行只进不出冻结几天)
- 公积金可以更改银行卡吗(省公积金可以转市公积金吗)
- 头条焦点:车没买交强险上路会怎么样(车辆不购买交强险会怎样)
- 世界球精选!LG与韩华联手布局美国储能市场
- 天天快看点丨2023年开始,电价大改?取消阶梯电价?以后电费怎么交
- 世界今头条!电力体现时空价值,2023年能源监管工作之储能看点
- 刚办的信用卡还款日账单日怎么算(如何计算信用卡还款日和出账日)
- 全球简讯:200MW/400MWh,宁夏能发新能源宁东储能示范项目EPC招标
- 当前头条:黄金交易提醒:市场目光转向美国GDP数据,金价仍有上行机会
- 环球百事通!现货黄金交易策略:美国GDP数据前部分多头获利了结,金价短线回调
- 全球播报:美原油交易策略:经济衰退担忧回升,油价短线下行风险增加
- 环球视点!以岭药业创新专利中药惠及海内外
- 金价创十年来最佳开年表现,接近技术牛市
- 天天时讯:巴克莱预测英银2月决议鹰派,建议提前抛售欧元兑英镑!
- 世界快消息!启程2023丨房地产行业如何面对新的一年?圈里圈外许下新年愿景
- 天天百事通!安本股票部研究与投资流程主管安德鲁·米林顿:股市有温和上行潜力,2023年可能是“优质股”之年
- 环球观察:中国动力电池产能占全球的比例有多大?
- 一美元等于几元 一美元是多少人民币(一美元等于几元 一美元是多少人民币)
- 网商贷怎么借钱 网商贷如何借钱(网商贷借钱操作流程)
- 热讯:2021上海gdp总量(全国gdp排名2021最新排名,上海市gdp超4万亿)
- 资讯:什么是汇率? 什么叫汇率(什么是汇率? 什么叫汇率)
- 特隆美储能20MW/100MWh阿里中广核储能电站项目成功并网
- 龙头增速超40倍!全球储能锂电池出货量再创新高
- 发挥智能路由功能 钱小乐助力金融端与流量端精准对接
- erc20是什么币(erc是什么币)
- 全球快资讯丨等额本息 30年提前还款技巧(等额本金20年第几年提前还款合适)
- 银行反馈此卡不可用怎么解决(银行卡反馈此卡不可用怎么办 银行反馈此卡不可用是怎么回事)
- 支付宝手续费 支付宝的手续费要多少(支付宝手续费 支付宝的手续费要多少)
- 短讯!95511怎么转人工(95511怎么转人工服务)
- 热点评!集合竞价挂单撤单规则,有以下3项(集合竞价挂单撤单规则,有以下3项)
- 世界热头条丨办信用卡被拒了多久才能再申请(信用卡被拒多久可以重新申请 信用卡被拒什么时候可以)
- 天天最资讯丨基金转换是按当天的净值买入吗(基金转换是按当天的净值买入吗)
- 天天消息!2020年成都查征信网点地址(成都自动查询征信网点)
- 当前信息:股票复权有什么影响?(股票里后复权是什么意思)
- 新春佳节际 年味至浓时 看湖南市场监管人忙碌的身影......
- 【天天热闻】公募密集调仓 重点加仓五大板块!今年基金投资思路在这里
- 【天天新要闻】法币怎么换成人民币(法币怎么换成人民币)
- 视讯!在途余额是什么意思(在途余额是什么意思啊)
- 医疗保险怎么报销,分以下三步计算(农村合作医疗怎样报销)
- 重点聚焦!安全风险点指的是什么意思(安全风险点指的是什么)
- 速讯:360块钱的保险是什么险种(360元保险是哪个保险公司的)
- 【热闻】借呗多久提高一次额度(借呗多久提额一次)
- 当前播报:房屋抵押贷款怎么贷(房产抵押贷款怎么贷,有以下五个步骤)