当前位置:编程学习 > VB >>

我做了一个程序,却不知流程图怎么画,谁能帮帮忙?

地址mysterybox@126.com
密码stupid123
里面的客户端.vbp和服务器端.vbp帮忙画一下流程图 服务器 --------------------编程问答-------------------- .....从来不画流程图的路过 --------------------编程问答-------------------- 感觉你是从史前穿越过来的原始人。

给你说说计算机的历史,以及为什么流程图早在20年前就像CRT显示器、软盘驱动器一样被扫进历史的垃圾堆。

在很早期,BASIC还不是一种结构化的编程语言,没有诸如If...End If以及Select...Case这样的结构化语句,更没有函数和子程序的概念。而且——程序依赖行号,程序总是从行号小的地方开始执行,就算你把语句写在后面,只要它行号足够小,它也是先执行。

这导致了一件很尴尬的事情,写程序之前如果不打草稿,你想在两条语句中间插入几行,而这两条语句行号相邻,那么这变得很困难,你不得不调整后面的行号,腾出地方容纳新的语句——别着急,你的程序还有很多GOTO语句呢,它们指向了某些行号,你打算更改行号,不得不连带修改引用这些行号的GOTO语句,这听上去已经能把人晕倒了,别着急,在那个年代,甚至我们还没有一款能上下左右移动光标的全屏幕编辑器……你试试看怎么写程序。再说读程序的人,更加夸张,他看到100 IF I > 10 THEN 510,然后转到510行(注意没有全屏幕编辑器),看到510行,510 IF J < 20 THEN 200,好吧,再折返回来,如果是一个多重的判断+循环,那能把人搞死。如果是你遇到这样的代码,你会怎么做?只要你不是足够的蠢,都会想到流程图。

用一系列的箭头描述GOTO的流程,再用方框表示每一个代码块做得事情,流程图可以很直观地表示代码要做什么,它就是那个“草稿”。

如果你用过VB,你就知道,if ... end if, for ... next, select ... case ... end select, function ... end function这样的层次结构把代码和代码之间的关系描述的一清二楚,配合良好的缩进,代码的可读性超过了流程图,你还想画流程图么?如果你想画流程图,就是对此一举——你画流程图需要很久的时间,而我说了,这些东西无论是编码还是作为别人阅读代码的参考都是没有价值的,最糟糕的是,代码经常变动,流程图也要跟着变,一旦两者不同步,反倒引起很多混淆,谁来维护流程图,谁来裁定流程图和代码的不一致,是编码的错误还是流程图的错误,流程图用什么工具维护,产生的文件如何随项目源代码组织?

我们从一个特别的视角来看结构化编程和非结构化编程吧,非结构化编程,我们的代码是一维的,线性的,代码一行一行写下去,虽然GOTO可以改变代码的执行方向,但是这些高层次的结构信息在代码层面是无法体现的。

在结构化编程的时代,我们不需要流程图了,因为流程图包含的信息在代码中已经反映了出来。但是新的问题来了,程序被划分成了很多函数,我们从一个函数调用另一个函数。那么当我们有了很多函数,新的麻烦出现了,我们发现一个大程序的一个函数很好,我们想在另一个程序中利用,于是我们把这个函数代码拷贝了出来,放入新的程序——程序并不能工作,为什么呢?很简单,这个函数中调用了另一个函数,显然这个函数仅仅存在在原来的程序中,好吧,我们在那个程序中搜索了一番,然后把那个函数拷贝了出来,又放入新的程序,程序还是不能运行!你猜到了,这个函数又调用了另一个函数,好吧,忙活了半天,眼看搞好了,突然,你发现了一个大灾难!什么灾难呢,你拷贝的第99个函数的函数名和你新程序中一个已经存在的函数的函数名相同,你必须修改其中的一个,而这种修改将会导致调用函数名的地方全部都要修改。于是又得想办法了,我们需要一个调用关系图,或者叫程序模块框图。

到了面向对象的时代,这个问题有了新的解决方式,我们可以用类将功能相关的方法和用到的数据加以组织,面向对象的类的组合、继承和聚合表达了他们之间的依赖关系,又有原本设计层面的信息被包含在代码中了,观察面向对象的程序的代码,不需要什么程序模块框图,也能很清晰看懂程序的组织结构。

还是刚才的视角,我们说结构化代码是二维的,一个维度是代码本身,一个维度则表明了它们的流程和层次,但是模块的依赖关系还是无法体现出来的,那么面向对象就是三维的,第三个维度,模块的依赖和组织被用代码表示出来了。

多说几句,其实还有第四个维度、第五个维度……很多使用VB的程序员也就看到第三个维度了,那么第四个维度是什么呢,对依赖关系和代码流程的复用——一个VB程序员明白如何将“公共”的代码提取成一个方法,而一个方法/函数本身做什么事情是确定无疑的。那么当我们的需求和函数的实现略有差异怎么办呢,一个典型的VB程序员的做法是,给这个函数增加一个参数,把两个不同需求作为这个参数,在函数里面判断。这意味着调用这个函数的用户,必须懂得修改这个函数的方法,并且越俎代庖代替函数的创建者修改它,还要处理现有代码对使用它的冲突。而一个C#程序员可以使用委托,使用委托使得函数编写者可以把细节的完善交给调用者,而他编写的代码只有算法的框架,细节和代码流程的分离在语言层面支持了,代码中不但包含了如何做的信息,还包含了做什么的信息——在此之前,做什么的信息是必须借助额外的文档说明的。

C#程序员也就只能看到第四个维度了,那么还有什么没有被包括进来呢?在C#程序员看来,程序是用来执行的,他们可能会编写一些小工具,把UML图转化为可以执行的程序,或者把程序转化成文档,他们可能会编写一些代码生成器产生那些冗繁而雷同的程序。前面我们说了,程序包含了原本是文档或者图中的信息,现在,我们可以说,既然如此,程序也可以被当作文档或者数据来被程序处理。程序本身只描述了它要做什么,至于它应该在上下文中做出怎样的行为,由它的上下文程序根据它的判断去完善这个程序——比如说,我们用javascript实现了一个算法,我们希望这个程序需要移植到GPGPU中运行,我们不需要人工去改写,我们知道,这个在CPU上运算的算法虽然无法直接在GPU上运行,但是它包含了算法应该如何做的全部信息,我们可以在运行时解析这个程序,而不是执行它,解析的目的是为了产生一个新的程序,新的程序适合我们的上下文(GPGPU),而这种代码变换由机器而不是人去处理——原先程序需要假设它的上下文,现在这些信息也不需要了。

注意,第五个维度是一个分界线——一个程序,去处理一个程序,而不是执行它,你觉得这件事情是编译器/解释器干的呢?还是库函数,用户编写的代码干的?我不知道。我不关心。因此,代码和控制代码运行的解释器/编译器的界限模糊了,这也意味着我们没有办法说它还是某种编程语言上写的一个程序,因为这个程序也可以看做是对这种语言语法的扩展。一种语言可以包含这种语言构成的原语,这意味着什么呢?这种编程语言可以模仿任何编程语言的任何特性,事实上,你可以说它是那种语言的一种方言。

当然还有第六、第七维度,过于学术,这里不说了。 --------------------编程问答--------------------
引用 1 楼 WallesCai 的回复:
.....从来不画流程图的路过


现在,我可以回答你之前的一个问题,为什么说“算法思想是通用的,语言只不过是工具”荒谬的不值得一驳。同时回答为什么会出现用一种编程语言可以把一个算法描述的比它的“思路”更加简洁。

我想我花了这么大的篇幅,从编程语言史观的角度已经很好地解释了这个问题,我只要总结下:因为编程语言的每一次进化,都把上一代语言how to do的信息纳入语言本身,从而简化为do what,在简化了人们关注问题复杂度的同时,使得我们可以从更加宏观的角度来分析问题。如果你拿相邻的两代语言去比较,你会发现同一个算法在它上面的实现仅仅是一个复杂,一个简单,一个概括,一个纠结了些细节而已,但是当你去审视诸如分布式的,大规模的解决方案中采用的算法的时候,以人脑的规模,你根本无法用最底层的语言去想象。今天我们解决问题的规模已经比20年前大了很多很多倍。当你用“思路”、“伪代码”去描述一个算法的时候,事实上只是把do what转化成更高层次的how to do,你可以再进一步的转化么?不可以,因为跳过一级,你的do what已经无法直接被转化为how to do了,你没有这样的工具,人脑连续抽象两次得到的“思路”是不精确的、粗糙的,因此而缺少价值。因此一种语言会束缚你思考问题的规模。 --------------------编程问答--------------------
引用 3 楼 caozhy 的回复:
引用 1 楼 WallesCai 的回复:.....从来不画流程图的路过

现在,我可以回答你之前的一个问题,为什么说“算法思想是通用的,语言只不过是工具”荒谬的不值得一驳。同时回答为什么会出现用一种编程语言可以把一个算法描述的比它的“思路”更加简洁。

我想我花了这么大的篇幅,从编程语言史观的角度已经很好地解释了这个问题,我只要总结下:因为编程语言的每一次进化,……


这是前面一个帖子的问题, 就不要引用这个帖子的回复么, 在前面那个帖子里最后的回复中我也提到了语言的差别带来的意识差异和编程习惯的差异. 
思路也好算法也好, 本身是一个抽象的东西.
你脑子里有思路有算法, 计算机并不能直接运行出任何东西来. 
你不得不借助于某一种计算机语言来把你的思路和算法给"具现"出来. 
而不同的语言有不同的特点和侧重, 所以才会产生了不同的代码不同的效率. 
这些不同点只是语言本身的特性而已. 
比如某个人很精通C同时也精通basic, 但如果交给他一个比较复杂的问题用编程来解决.  他可以用C去写,也可以用B去写. 思路不会有太大差别. 但是因为语言本身的区别,实现上就会有很大区别. 
其实我觉得在这个问题上没什么好多争论的. 无非是"方易做图"和"工具论"的翻版而已. 哪个都离不开另一个, 所以太绝对的话就纯属意气之争了.
坛子里面这种月经贴还少么. 
--------------------编程问答-------------------- 感觉你是从史前穿越过来的原始人。

给你说说计算机的历史,以及为什么流程图早在20年前就像CRT显示器、软盘驱动器一样被扫进历史的垃圾堆。

在很早期,BASIC还不是一种结构化的编程语言,没有诸如If...End If以及Select...Case这样的结构化语句,更没有函数和子程序的概念。而且——程序依赖行号,程序总是从行号小的地方开始执行,就算你把语句写在后面,只要它行号足够小,它也是先执行。

这导致了一件很尴尬的事情,写程序之前如果不打草稿,你想在两条语句中间插入几行,而这两条语句行号相邻,那么这变得很困难,你不得不调整后面的行号,腾出地方容纳新的语句——别着急,你的程序还有很多GOTO语句呢,它们指向了某些行号,你打算更改行号,不得不连带修改引用这些行号的GOTO语句,这听上去已经能把人晕倒了,别着急,在那个年代,甚至我们还没有一款能上下左右移动光标的全屏幕编辑器……你试试看怎么写程序。再说读程序的人,更加夸张,他看到100 IF I > 10 THEN 510,然后转到510行(注意没有全屏幕编辑器),看到510行,510 IF J < 20 THEN 200,好吧,再折返回来,如果是一个多重的判断+循环,那能把人搞死。如果是你遇到这样的代码,你会怎么做?只要你不是足够的蠢,都会想到流程图。

用一系列的箭头描述GOTO的流程,再用方框表示每一个代码块做得事情,流程图可以很直观地表示代码要做什么,它就是那个“草稿”。

如果你用过VB,你就知道,if ... end if, for ... next, select ... case ... end select, function ... end function这样的层次结构把代码和代码之间的关系描述的一清二楚,配合良好的缩进,代码的可读性超过了流程图,你还想画流程图么?如果你想画流程图,就是对此一举——你画流程图需要很久的时间,而我说了,这些东西无论是编码还是作为别人阅读代码的参考都是没有价值的,最糟糕的是,代码经常变动,流程图也要跟着变,一旦两者不同步,反倒引起很多混淆,谁来维护流程图,谁来裁定流程图和代码的不一致,是编码的错误还是流程图的错误,流程图用什么工具维护,产生的文件如何随项目源代码组织?

我们从一个特别的视角来看结构化编程和非结构化编程吧,非结构化编程,我们的代码是一维的,线性的,代码一行一行写下去,虽然GOTO可以改变代码的执行方向,但是这些高层次的结构信息在代码层面是无法体现的。

在结构化编程的时代,我们不需要流程图了,因为流程图包含的信息在代码中已经反映了出来。但是新的问题来了,程序被划分成了很多函数,我们从一个函数调用另一个函数。那么当我们有了很多函数,新的麻烦出现了,我们发现一个大程序的一个函数很好,我们想在另一个程序中利用,于是我们把这个函数代码拷贝了出来,放入新的程序——程序并不能工作,为什么呢?很简单,这个函数中调用了另一个函数,显然这个函数仅仅存在在原来的程序中,好吧,我们在那个程序中搜索了一番,然后把那个函数拷贝了出来,又放入新的程序,程序还是不能运行!你猜到了,这个函数又调用了另一个函数,好吧,忙活了半天,眼看搞好了,突然,你发现了一个大灾难!什么灾难呢,你拷贝的第99个函数的函数名和你新程序中一个已经存在的函数的函数名相同,你必须修改其中的一个,而这种修改将会导致调用函数名的地方全部都要修改。于是又得想办法了,我们需要一个调用关系图,或者叫程序模块框图。

到了面向对象的时代,这个问题有了新的解决方式,我们可以用类将功能相关的方法和用到的数据加以组织,面向对象的类的组合、继承和聚合表达了他们之间的依赖关系,又有原本设计层面的信息被包含在代码中了,观察面向对象的程序的代码,不需要什么程序模块框图,也能很清晰看懂程序的组织结构。

还是刚才的视角,我们说结构化代码是二维的,一个维度是代码本身,一个维度则表明了它们的流程和层次,但是模块的依赖关系还是无法体现出来的,那么面向对象就是三维的,第三个维度,模块的依赖和组织被用代码表示出来了。

多说几句,其实还有第四个维度、第五个维度……很多使用VB的程序员也就看到第三个维度了,那么第四个维度是什么呢,对依赖关系和代码流程的复用——一个VB程序员明白如何将“公共”的代码提取成一个方法,而一个方法/函数本身做什么事情是确定无疑的。那么当我们的需求和函数的实现略有差异怎么办呢,一个典型的VB程序员的做法是,给这个函数增加一个参数,把两个不同需求作为这个参数,在函数里面判断。这意味着调用这个函数的用户,必须懂得修改这个函数的方法,并且越俎代庖代替函数的创建者修改它,还要处理现有代码对使用它的冲突。而一个C#程序员可以使用委托,使用委托使得函数编写者可以把细节的完善交给调用者,而他编写的代码只有算法的框架,细节和代码流程的分离在语言层面支持了,代码中不但包含了如何做的信息,还包含了做什么的信息——在此之前,做什么的信息是必须借助额外的文档说明的。

C#程序员也就只能看到第四个维度了,那么还有什么没有被包括进来呢?在C#程序员看来,程序是用来执行的,他们可能会编写一些小工具,把UML图转化为可以执行的程序,或者把程序转化成文档,他们可能会编写一些代码生成器产生那些冗繁而雷同的程序。前面我们说了,程序包含了原本是文档或者图中的信息,现在,我们可以说,既然如此,程序也可以被当作文档或者数据来被程序处理。程序本身只描述了它要做什么,至于它应该在上下文中做出怎样的行为,由它的上下文程序根据它的判断去完善这个程序——比如说,我们用javascript实现了一个算法,我们希望这个程序需要移植到GPGPU中运行,我们不需要人工去改写,我们知道,这个在CPU上运算的算法虽然无法直接在GPU上运行,但是它包含了算法应该如何做的全部信息,我们可以在运行时解析这个程序,而不是执行它,解析的目的是为了产生一个新的程序,新的程序适合我们的上下文(GPGPU),而这种代码变换由机器而不是人去处理——原先程序需要假设它的上下文,现在这些信息也不需要了。

注意,第五个维度是一个分界线——一个程序,去处理一个程序,而不是执行它,你觉得这件事情是编译器/解释器干的呢?还是库函数,用户编写的代码干的?我不知道。我不关心。因此,代码和控制代码运行的解释器/编译器的界限模糊了,这也意味着我们没有办法说它还是某种编程语言上写的一个程序,因为这个程序也可以看做是对这种语言语法的扩展。一种语言可以包含这种语言构成的原语,这意味着什么呢?这种编程语言可以模仿任何编程语言的任何特性,事实上,你可以说它是那种语言的一种方言。

当然还有第六、第七维度,过于学术,这里不说了。  --------------------编程问答--------------------
引用 4 楼 WallesCai 的回复:
引用 3 楼 caozhy 的回复:引用 1 楼 WallesCai 的回复:.....从来不画流程图的路过

现在,我可以回答你之前的一个问题,为什么说“算法思想是通用的,语言只不过是工具”荒谬的不值得一驳。同时回答为什么会出现用一种编程语言可以把一个算法描述的比它的“思路”更加简洁。

我想我花了这么大的篇幅,从编程语言史观的角度已经很好地解释了这个问题,我只……


一个很简单的问题就能说明这一点。为什么在计算机诞生以前,那时的人没有掌握和发明算法,巴贝奇搞出了差分机,图灵建立了可运算性的理论。但是似乎都止步于此,这些思想虽然是伟大的,但是局限在机器实现上,是他们的思想不够么?是前人的智力不如今人么?错!是他们没有工具。

计算机科学的基本算法:排序、索引、查找都是60年代左右出现的,那时候有软件工程的理论么?同样没有。原因还是工具和工具解决问题的规模的限制。

任何思想都不能超脱他所处的现实,那种认为工具和思想不是相辅相成的观点,显然是不唯物的。 --------------------编程问答--------------------
引用 6 楼 caozhy 的回复:
一个很简单的问题就能说明这一点。为什么在计算机诞生以前,那时的人没有掌握和发明算法,巴贝奇搞出了差分机,图灵建立了可运算性的理论。但是似乎都止步于此,这些思想虽然是伟大的,但是局限在机器实现上,是他们的思想不够么?是前人的智力不如今人么?错!是他们没有工具。

计算机科学的基本算法:排序、索引、查找都是60年代左右出现的,那时候有软件工程的理论么?同样没有。原因还是工具和工具解决问题的规模的限制。

任何思想都不能超脱他所处的现实,那种认为工具和思想不是相辅相成的观点,显然是不唯物的。


请参考我之前的回复, 我向来都认同"思路"与"语言"并重. 并且在前一个帖子里我还特意例举了不同语言特性所带来的差异. 这种差异是客观存在的, 作为"依附"于某种语言开发的人来说, 只有充分掌握和利用到该种语言的特性的时候, 他写出的代码才可能是最有效的. 
但是毕竟计算机的语言差异还没有大到足以割裂思维的地步, 它们之间的共性依然可以被提取出来作为一种超越某一种语言特性的东西. 算法可以说是其中很小的一部分, 建立模型, 逻辑关系, 数据流向, 都是可以离开语言而讨论的东西. 

而语言, 也就是工具, 则是要在具体实施的阶段才会谈论到的东西了. 
同样一个项目, 一个程序, 换种语言或许只是开发周期和运行效率的差异, 但是换一种思路或者换一种数据表的结构甚至是换一种流程, 则会带来非常大影响.  --------------------编程问答--------------------
引用 7 楼 WallesCai 的回复:
引用 6 楼 caozhy 的回复:一个很简单的问题就能说明这一点。为什么在计算机诞生以前,那时的人没有掌握和发明算法,巴贝奇搞出了差分机,图灵建立了可运算性的理论。但是似乎都止步于此,这些思想虽然是伟大的,但是局限在机器实现上,是他们的思想不够么?是前人的智力不如今人么?错!是他们没有工具。

计算机科学的基本算法:排序、索引、查找都是60年代左右出现的,那时候有软……


反正我曾经和一些用VB的相当熟练的人讨论F#和Lisp,他们无法理解这些语言。别的我不想多说了,建立在你不了解的事实基础上的讨论毫无意义。 --------------------编程问答-------------------- 除 --------------------编程问答--------------------
引用 8 楼 caozhy 的回复:
反正我曾经和一些用VB的相当熟练的人讨论F#和Lisp,他们无法理解这些语言。别的我不想多说了,建立在你不了解的事实基础上的讨论毫无意义。


你说的确实没有错, 建立在不了解事实基础上的讨论毫无意义, 我只是就我所了解的软件项目来说, 从来未曾见过立项之初先讨论用什么语言, 然后再围绕这种语言的特性而展开的项目方式. 
或许真的有我所不知道的方式是如你所说的以开发工具为优先的. 但是那已经超出了我的认知范围.
--------------------编程问答-------------------- 流程图神马都是浮云 自己来吧 --------------------编程问答-------------------- 受教了!!! --------------------编程问答-------------------- 除 --------------------编程问答--------------------
引用 1 楼 WallesCai 的回复:
.....从来不画流程图的路过

应该是你没有用过好的UML工具,那是可以直接导出成代码的!
当然现在应该没人会将流程细化到语句一级,那是最没效率的方式。
但是至少,根据需求和业务流程,细化到业务函数一级的流程图;导出,整体架构就有了。

设计架构最怕与需求不符。总不能让用户看程序框架吧,所以流程图是最好的描述文档。 --------------------编程问答-------------------- 名字叫什么图关系不大,关键是表现出来你要的东西 --------------------编程问答-------------------- 很久没有画过流程图了... --------------------编程问答--------------------
引用 14 楼 Tiger_Zhao 的回复:
引用 1 楼 WallesCai 的回复:.....从来不画流程图的路过
应该是你没有用过好的UML工具,那是可以直接导出成代码的!
当然现在应该没人会将流程细化到语句一级,那是最没效率的方式。
但是至少,根据需求和业务流程,细化到业务函数一级的流程图;导出,整体架构就有了。

设计架构最怕与需求不符。总不能让用户看程序框架吧,所以流程图是最好的描述文档。
  ……


还真没用过那么高级的东西, 一般最多也就VISO画个图, 而且这也是负责项目沟通的部分, 主要用来和客户核对流程逻辑之用. 不会涉及到代码层次. 代码编写也用不到那么大的框框. 
实际上接触到的从"流程图" 到 "代码" 中间还差着好大一块呢. 
--------------------编程问答--------------------
引用 17 楼 WallesCai 的回复:
>引用 14 楼 Tiger_Zhao 的回复:
>引用 1 楼 WallesCai 的回复:
>……
还真没用过那么高级的东西, 一般最多也就VISO画个图, 而且这也是负责项目沟通的部分, 主要用来和客户核对流程逻辑之用. 不会涉及到代码层次. 代码编写也用不到那么大的框框. 
实际上接触到的从"流程图" 到 "代码" 中间还差着好大一块呢. 

其实就是细化不足。
最初的用户需求是“要做什么”,
然后细化成“业务上怎么做”,
你只少了一步细化成“软件会怎么做”——毕竟软件和人工的工作方式还是有差异的,要先与用户沟通并得到认同,才不会出现用户测试时“怎么是这样子的?”

又:其实设计书用文字或图都可以,但是图不容易有二义性,降低出成品后再扯皮的风险。 --------------------编程问答--------------------
引用 18 楼 Tiger_Zhao 的回复:
其实就是细化不足。
最初的用户需求是“要做什么”,
然后细化成“业务上怎么做”,
你只少了一步细化成“软件会怎么做”——毕竟软件和人工的工作方式还是有差异的,要先与用户沟通并得到认同,才不会出现用户测试时“怎么是这样子的?”

又:其实设计书用文字或图都可以,但是图不容易有二义性,降低出成品后再扯皮的风险。


其实"理论上"确实是这样子的, 从需求调查到分析到项目细化到代码, 如果每一步都做到位就能够得到双方满意的产品.

而实际上则受限于双方的表达/理解能力,行业熟悉程度,项目经理调配能力,程序员个人水平,公司资源等等因素的限制. 甚至到了后期发生需求改变也不是不可能的事. 
遇到比较纠结的case三番五次推倒重来也是有的. 

不过这些貌似扯得很远了.申明一下: 以下信息只代表本人的习惯, 若有雷同,纯属巧合.

我写程序, 至少小程序, 从来不画流程图! 
还有谁有意见么? --------------------编程问答-------------------- 所谓的胸有成竹、一挥而就,在小项目中完全可行。
其实软件工程不是为了“如何完美地做项目”,而是为了“问题是不可避免的,就想法减少出问题带来的损失”。
推倒重来无法完全避免,但是在前期推倒总比后期推倒好吧。
--------------------编程问答-------------------- --------------------编程问答--------------------  我学习一了一年多也不会现流程图``改天好好学习学习````
补充:VB ,  网络编程
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,