喜悦国际村 » 联盟项目组 » 与uml面对对象php编程,零距离亲密接触~~

页: [1] 2
开心果2003-12-31 12:09 PM
与uml面对对象php编程,零距离亲密接触~~

轻轻松松用UML设计PHP程序

[COLOR=red][B]作者:雨伞生日快乐(开心果原创)[/B][/COLOR]

[COLOR=red][B]一、为什么要用UML?[/B][/COLOR]
[B]1、面对对象编程,稳定、易扩展、结构清晰。避免了功能模块方法所存在的相互间联系不紧密、接口单一、二次开发劳命伤财、垃圾代码过多等弊端。居家旅行常备工具。[/B]
[B]2、有利于团队开发,特别是开源项目,任何时候任何人,拿到相关技术文档,立即可以投入工作。[/B]
[B]3、将编程和编码分离(偶自己的定义^^),程序员设计技术文档,打字员负责编码,极大地提高工作效率。[/B]

[COLOR=red][B]二、如何用UML设计面对对象的咚咚?[/B][/COLOR]
参见:
[url]http://www.phpx.com/happy/showthread.php?s=&threadid=47326[/url]
要不然就自己买书吧。

[COLOR=red][B]三、差不多是开工的时候了。[/B][/COLOR]
新闻更新系统为例,其实也不仅仅居然于此,反正就是管理一个种类kind和它下面的子件news的一个例子。偶刚学UML,水平有限,错误多多,有兴趣的看看吧。

[COLOR=red][B]1、系统需求[/B][/COLOR]
我们根据用户的需求,搜集整理系统需求。系统需求包括三类—功能性需求、非功能性需求、可用性需求。

[B]功能性需求[/B],大家都很了解,也就是能够让用户获得什么样的功能,仔细了解用户的意向后,我们不能得出系统应该实现的主要功能。我们在本实例中的功能需求如下

管理员添加、删除、编辑“栏目内容”kind和“新闻内容”news

[B]非功能性需求[/B],如系统的稳定性、安全性等。虽然曾经有人号称电子商务是30%的后台php代码+70%的前台javascrit特效,但是偶反对代码中镶嵌JS等动态代码,html等静态代码基本上没什么太大的问题,前提是不影响易读性。镶嵌一堆JS代码的PHP所谓功能模块,偶将其直接和垃圾划等号,毕竟电子商务不是电子花瓶。这一部分的工作,就看自己的职业道德了。

[B]可用性需求[/B],用户毕竟是用户,用户要的是易用性,而不管你如何去实现。一套合理的思维体系,往往让用户使用起来得心应手,这年头,有几个人是先看书再使用Office系列的产品了。在B/S模式中,瘦客户端(浏览者)的动态实现,目前多为JAVASCRIPT,偶只想在这里说的是,这是一把双刃剑,过分的依赖不仅会割伤了用户,也会割伤了自己。

[COLOR=red][B]2、需求分析[/B][/COLOR]
需求分析的主要任务就是识别系统的参与者和用例。

[B]识别参与者[/B]
本系统由几个参与者组成,本实例中仅用管理员(administrators)、浏览者(visitor)两个参与者。

[B]识别用例[/B]
说土一点,就是参与者所能执行的事件,如添加种类(addKind)、修改种类(updateKind)、删除种类(delKind)等。。。

[COLOR=red][B]3、绘制出简单的用例图[/B][/COLOR]
如下,管理员(administrators)可以管理、浏览kind和news,浏览者(visitor)仅能浏览。

开心果2003-12-31 12:10 PM
[COLOR=red][B]4、建立静态结构模型[/B][/COLOR]
[B]根据需求分析抽象出系统中的类[/B]
本例中我们设计kind类和news类这两个类,考虑到数据库的连接问题,我们设计了一个database类,进行基本的数据库操作,并且由database类派生出kind类和news类两个子类。这样,kind类和news类就继承了database父类的很多特性。

[B]绘制出系统的类图[/B]
也就是该类包含哪些方法、哪些属性,以及类之间的依赖等关系。如下图:

开心果2003-12-31 12:11 PM
[COLOR=red][B]5、根据类图设计系统的时序图[/B][/COLOR]
时序图也就是参与者操作的整个流程,比起过去的框框圈圈的流程图要直白得多,这里主要介绍一下删除种类(delKind)的流程,其他流程类似。

如下图,管理员(administrators)激活管理页面index.php的delKind()事件,该事件调用delKDialog.php中的createDialog(int,String)方法创建“删除种类窗口”。在管理员确认删除操作之前,让他明白自己准备删除的内容,是个不错的主意。所以,生成createDialog方法中,我们调用了kind类的returnNews()方法,将结果显示在所生成的确认删除窗口,告诉管理员它所即将删除的种类中有多少子件(新闻news)。管理员按下确认按钮,也可能是一个确认链接,激发delKDialog.php的delKind方法。后台根据传过来的种类的id,调用kind.class.php的kind(int)方法生成一个新的kind类,并同时调用该类的returnNews()方法查询该种类中现有的子件id的,并调用news.class.php的delNews()方法逐个删除。当然,如过你对自己的操作有足够的信心,并愿意承担由此引发的相关责任,你也可以一次性删除,具体根据个人习惯(大量删除时,一次性删除会快很多)。最后,调用我们kind.class.php的delKind()方法,实际的删除该种类kind。

开心果2003-12-31 12:12 PM
addKind

开心果2003-12-31 12:12 PM
editKind

开心果2003-12-31 12:13 PM
addNews

开心果2003-12-31 12:14 PM
editNews

开心果2003-12-31 12:14 PM
delNews

开心果2003-12-31 12:15 PM
[COLOR=red][B]6、根据类图和时序图编码[/B][/COLOR]
觉得这应该是打字员做的事情,你会发现:依靠详细的技术文档编码,是一件非常宁人愉快的事情,不需要太多的思考。即使若干天后,你重新再接着干,你也能很快的进入脚色;即使很不幸,你身边一位很得力的同事离开了你的团队,第二天来的新人也能依靠技术文档,立即投入与你并肩作战。这也就是为什么印度阿三的文档总是那么细致,代码却总是那么低劣,但系统却总是那么完善的原因。事实上,在文章的最后,你同时会发现,偶的代码确实也挺烂的^^,至少我是这么认为。

[COLOR=red][B]7、程序界面设计,包括页面[/B][/COLOR]
其实这部分,应该是在静态模型建立过程中,和类图一起生成的,但是由于种种原因,我放在了最后,不过请放心,你所需要做的仅仅是在页面得相应位置加入诸如showNews()等代码,模板同时也是一个不错的主意,更或者是将ADODB也引入database类的封装。我个人比较欣赏“模型、控制器、显示”的策略。

[COLOR=red][B]8、调试[/B][/COLOR]
基本上没有什么好调试的,不用像以往那样,调试改错的时间比编码的时间还要长得多得多。放弃以往那种生存方式吧,那绝对是在慢性自杀。

从下一个PHP程序开始,面对对象,使用可爱的[COLOR=red][B]UML[/B][/COLOR],你的生活将更加美丽。

[COLOR=red][B]9、类库代码[/B][/COLOR]

database.class.php

[php]
<?php
    class database {
        var $hostname = "localhost";
        var $username = "root";
        var $password = "pass";
        var $basename = "web";
        var $query    = "";
        var $result   = NULL;
        var $db       = NULL;

   /*
    //初始化
        function database() {
            $this->connect();
            $this->selectDatabase();
        }
        */

    //连接数据库
        function connect() {
            $this->db = @mysql_connect($this->hostname, $this->username, $this->password);
            if(FALSE == $this->db) {
                echo "无法正常连接数据库。";
                exit;
            }
        }

    //选择数据库
        function selectDatabase() {
            if(FALSE == mysql_select_db($this->basename)) {
                echo "无法正常打开选定的数据库。";
                return FALSE;
                exit;
            }
            return TRUE;
        }

    //设置语句
        function setQuery($myQuery) {
            if($myQuery == "") {
                echo "语句不能为空。";
                return FALSE;
            } else {
                  $this->query = $myQuery;
                  return TRUE;
              }

        }

    //更新数据库
        function store() {
            $this->result = mysql_query($this->query, $this->db);
            $this->query  = "";

        }

    //关闭数据库
        function closeDatabase() {
            mysql_close($this->db);
        }
    }

/*测试
    $test = new database;
    $test->setQuery("select * from class");
    $test->store();
    $row = mysql_fetch_array($test->result);
    echo "<pre>";
    print_r($row);
    echo "</pre>";
    $test->closeDatabase();
    */
?>
[/php]

kind.class.ph

[PHP]
<?php
    include_once("database.class.php");
    include_once("news.class.php");

    class kind extends database {
        var $idKind    = NULL;
        var $nameKind  = NULL;
        var $tableName = "web_kind";

    //初始化 没办法,只有PHP5才支持重载-_-#
        function kind() {
            $this->connect();
            $this->selectDatabase();
            switch(func_num_args()) {
                case 1  :  $this->setKindId(func_get_arg(0));
                           $this->setKindName($this->getKindName($this->idKind));
                        break;
                case 2  :  $this->setKindId(func_get_arg(0));
                           $this->setKindName(func_get_arg(1));
                        break;
                default :
                        exit;
            }
        }

    //是否已存在,返回数目
        function findKind() {
            $this->setQuery("select count('kind_id') from $this->tableName");
            $this->store();
            $numKind = mysql_fetch_array($this->result);
            return $numKind[0];
            mysql_free_result($this->result);
        }

    //添加种类
        function insertKind() {
            $this->setQuery("insert into $this->tableName set kind_name = '$this->nameKind' ");
            $this->store();
            return $this->result;
        }

    //修改种类
        function updateKind() {
            $this->setQuery("update $this->tableName set kind_name = '$this->nameKind' where kind_id = '$this->idKind'");
            $this->store();
            return $this->result;
        }

    //删除种类
        function delKind() {
            $this->setQuery("delete from $this->tableName where kind_id = '$this->idKind'");
            $this->store();
            return $this->result;
        }

    //显示种类列表,可以自行定义样式
        function showKind() {
            $this->setQuery("select * from $this->tableName order by kind_id");
            $this->store();
            echo "<ul>";
            while($row = mysql_fetch_array($this->result)) {
                echo '<li><a href="'.$row["kind_id"].'">'.$row["kind_name"].'</a></li>';
            }
            echo "</ul>";
            mysql_free_result($this->result);
        }

    //返回Kind类的id
        function returnKindId() {
            return $this->idKind;
        }

    //返回Kind类的name
        function returnKindName() {
            return $this->nameKind;
        }
    //设置Kind类的name,检查长度等操作
        function setKindName($name) {
            if(strlen($name) >= 12) {
        //Call errorDialog
                exit;
            } else {
                  $this->nameKind = $name;
                  return TRUE;
              }
        }

    //设置Kind类的id,防止非正整数等
        function setKindId($id) {
            if($id < 0) {
        //Call errorDialog
                exit;
            } else {
                  $this->idKind = $id;
                  return TRUE;
              }
        }

    //获得Kind类的name
        function getKindName() {
            $this->setQuery("select * from $this->tableName where kind_id = '$this->idKind'");
            $this->store();
            $KindName = mysql_fetch_array($this->result);
            return $KindName["kind_name"];
        }

    //获得该类的子件,555555~~,要是用PHP5该多好啊
        function returnNews() {
            $myNews = new news(0, $this->idKind, "NONE", "NONE");
            return $myNews->returnNewsOfType();
        }
    }


  /*测试
      */
    $myKind = new kind(1);
    echo $myKind->showKind();
    $test = $myKind->returnNews();
    echo "<pre>";
    print_r($test);
    echo "</pre>";
    $myKind->closeDatabase();
      /*
  */
?>
[/PHP]

news.class.php

[PHP]
<?php
    include_once("database.class.php");

    class news extends database {

        var $idNews    = NULL;
        var $typeNews  = NULL;
        var $titleNews = NULL;
        var $textNews  = NULL;
        var $tableName = "web_news";

    //初始化
        function news() {
            $this->connect();
            $this->selectDatabase();
            switch(func_num_args()) {
                case 1  :  $this->setNewsId(func_get_arg(0));
                           $this->getNewsInfomation();
                        break;
                case 4  :  $this->setNewsId(func_get_arg(0));
                           $this->setNewsType(func_get_arg(1));
                           $this->setNewsTitle(func_get_arg(2));
                           $this->setNewsText(func_get_arg(3));
                        break;
                default :
                        exit;
            }
        }

    //插入News
        function insertNews() {
            $this->setQuery("insert into $this->tableName set
                                    news_type  = '$this->typeNews',
                                    news_title = '$this->titleNews',
                                    news_text  = '$this->textNews'");
            $this->store();
            return $this->result;
        }

    //修改News
        function updateNews() {
            $this->setQuery("update $this->tableName set
                                    news_type  = '$this->typeNews',
                                    news_title = '$this->titleNews',
                                    news_text  = '$this->textNews'
                             where news_id = '$this->idNews'");
            $this->store();
            return $this->result;
        }

    //删除News
        function delNews() {
            $this->setQuery("delete from $this->tableName where news_id = '$this->idNews'");
            $this->store();
            return $this->result;
        }

    //返回同一标题的内容数目
        function returnNumTitle() {
            $this->setQuery("select * from $this->tableName where news_title = '$this->titleNews'");
            $this->store();
            return mysql_num_rows($this->result);
            mysql_free_result($this->result);
        }

    //返回同一种类的子件id
        function returnNewsOfType() {
            $this->setQuery("select news_id from $this->tableName where news_type = '$this->typeNews'");
            $this->store();
            while($row = mysql_fetch_array($this->result)) {
                $NewsId[] = $row["news_id"];
            }
            return $NewsId;
        }

    //设置News类id
        function setNewsId($id) {
            if($id < 0) {
                exit;
            } else {
                  $this->idNews = $id;
                  return TRUE;
              }
        }

    //设置News类type
        function setNewsType($type) {
            if($type < 0) {
                exit;
            } else {
                  $this->typeNews = $type;
                  return TRUE;
              }
        }

    //设置News类title
        function setNewsTitle($title) {
            if($title == "") {
                exit;
            } else {
                  $this->titleNews = $title;
                  return TRUE;
              }
        }

    //设置News类text
        function setNewsText($text) {
            if($text == "") {
                exit;
            } else {
                  $this->textNews = $text;
                  return TRUE;
              }
        }

    //设置News类type/title/text信息,偶比较懒^^
        function getNewsInfomation() {
            $this->setQuery("select * from $this->tableName where news_id = '$this->idNews'");
            $this->store();
            $NewsInformation = mysql_fetch_array($this->result);
            $this->setNewsType($NewsInformation["news_type"]);
            $this->setNewsTitle($NewsInformation["news_title"]);
            $this->setNewsText($NewsInformation["news_text"]);
            mysql_free_result($this->result);
        }

    //返回id
        function returnId() {
            return $this->idNews;
        }

    //返回type
        function returnType() {
            return $this->typeNews;
        }

    //返回title
        function returnTitle() {
            return $this->titleNews;
        }

    //返回text
        function returnText() {
            return $this->textNews;
        }


    }

/*调试
    */
    $myNews = new news(3);
    echo $myNews->returnNumTitle();
    $test = $myNews->returnNewsOfType();
    echo "<pre>";
    print_r($test);
    echo "</pre>";
    $myNews->closeDatabase();
    /*
*/
?>
[/PHP]

数据结构

[CODE]
CREATE TABLE web_kind (
  kind_id int(11) NOT NULL auto_increment,
  kind_name varchar(50) NOT NULL default '',
  PRIMARY KEY  (kind_id)
) TYPE=MyISAM;

CREATE TABLE web_news (
  news_id int(11) NOT NULL auto_increment,
  news_type int(11) NOT NULL default '0',
  news_title varchar(100) NOT NULL default '',
  news_text text NOT NULL,
  PRIMARY KEY  (news_id)
) TYPE=MyISAM;

[/CODE]
[COLOR=red][B]10、后记[/B][/COLOR]
本文主要依赖PHP4,进入PHP5后,本文就是垃圾;考虑到PHP5仍需时间,所以没有采用PHP5编码。

本文的主旨是表明设计思想,自己比较懒,也不想再检查什么,看见错误就不要Q偶啦。

之所以放到这个板块,是觉得项目组如果有一个资深系统分析员带队,事情会变得很简单。既然大大不愿/不屑出面,本极品菜鸟本着“JUST DO IT”的原则,献丑了。^^

[COLOR=red][B]11、撰写本文的真正目的^^[/B][/COLOR]

亲爱的雨伞

好久没你消息了

这两天总想你

心里很乱

寻遍你爱去的池塘

就餐的小屋

睡觉的草坪

仍不见你踪影

我心都快碎了











养这么大的猪,咋就丢了呢

       猪,你生日快乐!^^

——开心果到此一游

    2003年11月11日

roseangel2004-1-1 06:37 AM
11、撰写本文的真正目的^^

亲爱的雨伞

好久没你消息了

这两天总想你

心里很乱

寻遍你爱去的池塘

就餐的小屋

睡觉的草坪

仍不见你踪影

我心都快碎了


偶的乖乖~
看到后面偶的眼睛都看直了
先收藏再说
:D :D :D :D :D

KnightE2004-1-24 07:00 PM
顶~~~:D

火龙sky1号2004-1-25 02:09 AM
啦 啦 啦 啦 !!!!

Roast Duck2004-1-29 06:41 AM
good!

lad2004-2-5 05:41 AM
纵使头顶有千万个包,偶也要顶呀~~~:D

slackware2004-2-5 08:07 AM
8错

KnightE2004-3-9 07:50 PM
果子在忙啥呢??
想找你帮忙用UML做设计都不见你人哪:(

开心果2004-5-17 11:54 AM
一直有个梦想∶国内PHP形式与数据分离、应用与逻辑分离、编码与设计分离、数据库语句与PHP分离。。。。一人编写,大家受益。。。。。陶醉~~

(不介意偶再顶一下下吧:D)

建模的误区—— 走出一般性的设计误区,迈向成功之途

作者:Scott Ambler 翻译:luckygao 来源:[url]http://www.sdmagazine.com/documents/s=844/sdm0108k[/url]

译注:本文翻译未征得作者同意,仅作练习。

==============================================================================

无论你遵从的是重量级的方法,比如Enterprise Unified Process(EUP),还是轻量级的开发过程,如Extreme Programming(XP),建模在软件开发中都是不可或缺的。但不幸的是其中充斥着各种谬误与迷思。
这来自于各个方面,有从理论家错误的研究、数十年来信息技术领域内的文化沉积、软件工具开发商天花乱坠半的市场宣传以及象Object Management Group (OMG)和IEEE这类组织的标准。这个月,我要揭示建模中 的误区,指出其相应的事实真相。


误区一:建模就等于是写文档

这很可能是其中最具破坏力的一条,因为开发人员可以此为借口而完全放弃建模。许多优秀的软件开发人员 会说他们不想把时间浪费在这些“无用的“文档上。他们沉溺于编码之中,制造着一些脆弱而劣质的系统。
另外,甚至于许多尽责的开发人员现在也认为建模是一件讨厌的事,而不愿去学习相应的建模技术。


事实分析:“模型”与“文档”这二者在概念上是风马牛不相及的—你可以拥有一个不是文档的模型和不是模型的文档。一幅设计图就是一个模型,而不论是被画在餐巾纸的背面,或写在一块白板上,或在Class Responsibility Collaboration(CRC)卡片中,还是根据记录在报纸和便签纸上的流程图而生成的一个粗略的用户界面原型。虽然这些都不能说是文档,但他们却都是有价值的模型。


建模很象是作计划:作计划的价值在于计划编制的过程中,而非计划本身;价值体现在建模的活动中,而非 模型本身。实际上,模型不是你系统中的一部分正式的文档,而且在完成它们的使命后可以被丢掉。你会发现值得保留的只有很少的模型,而且它一定是非常完美。

误区二:从开始阶段你可以考虑到所有的一切

这种说法流行于二十世纪七十年代到八十年代早期,现今的许多经理都是在那个时候学习的软件开发。对这 一点的迷信会导致在前期投入可观的时间去对所有的一切建模以期把所有一切都弄正确,试图在编码开始前就“冻结”所有的需求(见误区四),以致于患上“分析期麻痹症” – 要等到模型非常完美之后才敢向前进。基于这个观点,项目组开发了大量的文档,而不是他们真正想要得到的—开发满足需要的软件。


事实分析:怎么才能走出这个误区呢?首先,你必须认识到你不能考虑到所有的细枝末节。第二,认识到编码员可能会对建模者的工作不以为然(这是可能的,事实上建模者所作的工作在实际价值中只占很少的部分),他们或许会说模型没有反应出真实的情况。第三,认识到不管你的最初所作的规格说明书有多好,但 注定代码会很快地与之失去同步,即便是你自己建模自己编码。一个基本的道理就是代码永远只会和代码保 持一致。第四,认识到迭代法(小规模地建模,编一些代码,做一些测试,可能还会做一个小的工作版本)是软件开发的准则。它是现代重量级的软件开发过程(如EUP),以及轻量级(如XP)的基本原理。


误区三:建模意味着需要一个重量级的软件开发过程

走入这个误区(经常与误区一有联系)的项目组常常是连建模都彻底地放弃了,应为这样的软件开发过程对 他们来说太复杂太沉重了。这不亚于一场天灾。


事实分析:你可以用一种轻灵的方式取而代之。关于用简单的工具进行简单地建模的详细内容可参看Agile Modeling(AM)。而且,你可以丢弃你的模型当使命完之后,同样也可以很基本的方式进行建模(比如,从办 公桌起来,来到白板前就开始构略草图)。只要你愿意,你就可以轻松地建模。


误区四:必须“冻结”需求

这个要求常常来自高级经理,他们确切地想知道他们从这个项目组能得到什么东西。这样的好处就是在开发 周期的早期确定下需求,就可以确切地知道所要的是一个什么样的东西;缺点就是他们可能没有得到实际上 所需要的(不全或错误的需求,译者)。


事实分析:变化总会发生的。由于优先级的变化和逐渐对系统有了更进一步的理解,都会引起需求的变化。 与冻结需求相反,估计项目成功的风险,尽量去接受变化而且相应地采取行动,就象XP所建议的一样。

误区五:设计是不可更改的

如同误区四,要求每一个开发人员必须严格遵从“设计“,导致开发人员为了符合“设计“而作了错误的事情或以错误的方式作正确的事情。或者是简单地忽略了设计,否定了所有设计可能带来的好处。冻结了设计,你就不能从在项目进程中所学到知识进一步获益。另外一个很大的趋势就是开发出大量的文档而不是实 际的软件,使用面向文档的CASE工具而不是能给项目带来实际价值的面向应用的工具。


事实分析:事实上,设计会经常根据开发人员和数据库管理员的反馈进行修改,因为他们是最接近实际应用 的人,通常他们对技术环境的理解要好于建模者。我们必须的面对这样一个事实:人无完人,他们所作的工 作也不可能尽善尽美。难道您真的想将一个并不完善的设计固定下来而不再去修改其中的错误吗?另外,如 果需求并没有被冻结,其实就意味着你不能冻结你的设计,因为任何需求的修改势必影响设计。对之,正确 的态度是:只要你的代码还在改动,涉及就没完。


误区六:必须使用CASE工具

建模常常被认为是一项复杂的工作,因此需要大量地使用CASE工具辅助进行。


事实分析:是的,建模可以是很复杂的。但你完全可以建立一个有效而简单的模型表述其中关键的信息,而 不是将一些无关紧要的细节包括进来。


比如,我经常使用UML建立模型来表示类、它们的属性及一些关键的业务操作,但并不画出属性的存取操作 (get和set),以及维护与其它类关系的框架代码,或者其他一些琐碎的实现细节。我通过建模寻找解决问题的方法,让我和我的同事能继续前进去实现这个模型。以这样灵活的方式,大多数情况下我并不需要一个 CASE工具来支持建模工作,一块白板,或者一台数字相机足以。这样,我就不用花时间去评估CASE工具,不 用去和工具供应商讨论许可证的问题,也免去了人员培训开销。CASE工具只有当它能体现最佳性价比时(相 对你自己的情况而言),才值得购买。大多数情况下,我都能不用它而达到目的(完成建模)。我经常使用 的工具有Together/J([url]http://www.togethersoft.com/[/url]) – 因为它能产生数目可观的Java框架代码;还有ERWin([url]http://www.cai.com/)[/url] -- 因为它能规划数据库。这两个工具真正地帮助我实现了软件开发的目的 – 制造满足用户要求的软件。但我绝大多数得建模工作仍然使用的是简单的工具,而不是CASE工具。


误区七:建模是在浪费时间

许多新手都这样认为,这主要是因为他们所接受的教育仅仅局限于如何编写代码,对于完整的开发流程鲜有接触。而且他们的经验也仅限于如何实现代码,就如初级程序员。他们放弃了提高效率和学习技能的机会,这些技能能够使他们很容易地适应不同的项目或组织。他们应该为此感到羞愧。


事实分析:在大多数情况下,在开始编码之前画一个草图、开发一个粗率的原型或者制作一些索引卡片都能提高你的生产效率。高效的开发者在编码之前都要进行建模工作。另外,建模是一种很好的在项目组成员与项目负责人之间沟通途径。你们在这个过程中探讨问题,从而对所要的是一个什么样的东西可以得到更好的 理解,涉及到该项目中的每个成员也可得到对该项目有一个从分的了解。


误区八:数据模型(Data Model)就是一切

许多组织基于数据模型就蹒跚启动新的开发工作,也许正如你所在的组织:IT部门对于数据有非常严格的规 定,控制着你的开发项目;或者你以前的数据库是一团糟,别无选择。


事实分析:数据模型是一个重要的但不是最重要的建模,它最好是建立在另外的模型之上。(参见 “Extreme Modeling”,Thinking Objectively,Nov.2000)。这即使在象数据仓库这类面向数据的项目中 也如此。如果没有很好的理解用户是如何使用该数据仓库的(在数据模型中没有表示出来),这些项目经常 是以可悲的失败而告终。你可以使用的模型有很多 – 使用案例(use cases),业务规则(business rules),activity diagrams,类图(class diagrams),component diagrams,用户界面流程图(user interface flow diagrams)和CRC,等等。数据模型仅仅是其中的一种。每种模型都有其长处和短处,应该
正确地使用。


误区九:所有的开发人员都知道如何建模

我们现在面临照这样一个严重的问题:许多不是开发人员的人,包括高级经理和用户,不知道软件是如何建 成的。其结果,他们不能够区分开熟练的开发者和一般的程序员(当然也分不清高级程序员和一般程序 员),他们想当然地认为所有的开发人员都具备从头到尾开发整个系统的技能。


事实分析:这肯定是不正确的。建模的技能,是只有当一个开发者通过学习它,并经过长期的实践才能够掌握。一些非常聪明的程序员常常相信自己无所不能,毕竟他们终究只是程序员。正因为这样的狂妄自大,他们承当的一些任务是他们根本就没有相应的技能去完成的。软件开发是如此的复杂,单单一个人是很难具备所有的技能去成功地进行开发,甚至也不可能去配置有一定复杂程度的系统。开发这应该有自知之明,明白他们自己的弱点,学无止境。通过互相取长补短,建模者可从程序员身上学到一项技术的具体细节,程序员也可从建模者那里学到有价值的设计和体系结构的技术。我个人认为所有的人,包括我自己,都是新手。


Agile Modeling

通过理解和避开建模的误区,你能够是得你自己、你的项目组和你的组织更加有效地进行软件开发。在揭示 这些普遍存在误区的过程中,我已经表述了Agile Modeling(AM)的许多原则。Agile Modeling 以前叫做 Extreme Modeling(XM)。我希望我所给于你的是精神上的食粮。


在此我要感谢Blueprint Technologies([url]http://www.blueprinttech.com)的Doug[/url] Smith,Evanetics ([url]http://www.evanetics.com)的Gary[/url] Evans,以及在Agile Modeling邮件列表(可访问 [url]http://www.agilemodeling.com加入)中对本文做出贡献的人们。我同样要感谢Martin[/url] Fowler,Ron Jeffries和其他一些XP社区中成员,因为我想我已经融入了一些他们的观点。


建模十条原则

仅有数据模型对于现代软件是不够的。
接收变化,并且允许你的模型能够随着时间进行改进。 你不能冻结它们,然后就期待着成功。
模型并不一定就是文档,文档也不一定就是模型。
大多数的模型可能也应该被丢弃。
只有代码才能与代码保持真正的同步。
一些简单的工具,比如白板,就完全足以应付大多数建模工作。
思考,然后再编码。
你总能从别人身上学到东西。
建模可以用一种轻盈的方式。
设计直到代码发布以后才算完成。

yuguanglou2004-5-17 12:18 PM
好啊 顶

不过 这个雨伞就是村里的雨伞???
难道果子和他也有一腿? :blowzy: :blowzy:

开心果2004-5-17 01:14 PM
[QUOTE][i]最初由 yuguanglou 发布[/i]
[B]好啊 顶

不过 这个雨伞就是村里的雨伞???
难道果子和他也有一腿? :blowzy: :blowzy: [/B][/QUOTE]

村子那个不认识。。。。Umbrella很多年前就这么叫了。。。MM:blowzy:

偶认识她也是因为。。。。。当年的"生化危机"

那个时候MM自己做滴战旗:D

mgirl2004-5-17 02:23 PM
偶终于也可以顶了


查看完整版本: 与uml面对对象php编程,零距离亲密接触~~


Powered by Discuz! Archiver 6.1.0  © 2001-2006 Comsenz Inc.
Processed in 0.008039 second(s), 2 queries