观's profileTo the world,you may jus...PhotosBlogListsMore Tools Help

Blog


    04/07/2009

    嵌入式UI架构设计

    //========================================================================
    TITLE: 嵌入式UI架构设计漫谈
    AUTHOR: norains
    DATE: Friday 31-October-2008
    Environment:  NONE
    //========================================================================

        和桌面清一色的采用explorer不同,嵌入式设备更多的采用是自定义的简单UI,即使是含有explorer的wince也是如此。因为对于嵌入式设备而言,功能强大并不是主打,简单易用才是根本。以目前国内的手持车载设备为例,大部分的公司卖的都是硬件,利润很大一部分取决于硬件成本的多寡。并且,每个系列的产品都会有不同的外围器件,而这也决定了无法所有的产品都用同一个UI程序。
        
        虽然UI程序无法使用同一个,但从总体上而言,基本上是相同的;最有可能不同的地方无非是界面多了某些按钮,调用某些功能而已。另一方面,UI程序往往也需要配合产品的外观,风格尽可能和外观相符合。
        
        于是由此,基于可重用性考虑,嵌入式设备的UI基本上必须具有如下特点:
        1.界面更换方便
        2.功能增删方便
      
        下面我们就这两点具体到代码的层次去说说相应的设计。
        
        界面更换方便,这个方便不仅是对于程序编写者而言,也是针对图片设计者。如果是方案提供商,则后者显得更为重要。如果程序能够做到每次更换图片不需要重新编译,那么对于客户而言,他们只需要重新设计图片,然后替换就能立马看到效果。这点是非常重要的,如果每更换一次图片就必须要重编译,意味着多一个客户就会多一个烦恼。
        
        以读取BMP图片为例,最简单的方法就是将bmp图片导入到IDE环境的resource中,在使用的时候调用MAKEINTRESOURCE宏来获取相应的字符串地址即可。不过这会有一个非常严重的问题,因为图片是全部包含于可执行文件中,如果图片很多容量很大,那么单一的可执行文件的大小就会非常可观了。何况在wince中还会有个问题,如果程序体积大于8M,那么读取程序内部包含的图片将有可能会导致失败。
        
        鉴于以上原因,图片放在外部读取是最佳的选择。
        
        如果图片放在外部存储器,读取的速度将是一个不能忽略的问题。假使一张bmp图片的大小为800*480,然后再加上界面上的ICON,如果每次显示时都会分配缓冲然后绘制图片,那么会感觉到有延迟。一般像这种情况之下,我们都会选择一次读取,多次使用的方式。也就是说,只有第一次使用的使用才会将图片保存到缓冲区,以后都只是从这缓冲区获取图片数据而已。
        
        为了能够最大限度节省内存,以及使用的便利性,我们将对图片的读取和获取采用类封装的形式。最为简便的方式是,我们传入一个图片的序号,然后获取一个可供绘制的HDC。
        
        基本的形式概括如下;
        namespace ImageTab
        {
         enum ImageIndex
         {
          NONE,
          BKG_WND_MAIN,
          
          ...
          
          }
          
         struct ImageInfo
         {
          HDC hdc;
          SIZE size;
         }; 
        }

        class CImageTabBase
        {
        public:
         bool GetImageInfo(ImageTab::ImageIndex imgIndex, ImageTab::ImageInfo &imgInfo) ;
         
         ...
        }

        绘制图片时可以简单如此:
        ImageTab::ImageInfo imgInfo = {0};
        if(m_ImgTab.GetImageInfo(m_BkInfo.Image,imgInfo) != false)
        {
         StretchBlt(memDC.GetDC(),0,0,iWndWidth,iWndHeight,imgInfo.hdc,0,0,imgInfo.size.cx,imgInfo.size.cy,SRCCOPY);
        }

        使用类的方式还有一个好处,就是如果遇到图片架构变更,只要添加新的ImageTab类即可,甚至可以通过配置文件来确定当前运行的程序应该选用何种界面:
        switch(m_Option.GetImgTab())
       {
        case Option::IMG_A:
         m_pImgTab = new CImageTabA(); 
         break;
        case Option::IMG_B:
         m_pImgTab = new CImageTabB(); 
         break;
        default:
         m_pImgTab = new CImageTabA(); 
         break;
       }
       
       这对于需要频繁更改界面的需求无疑是一个比较好的方式。
       
       
       和图片类似,显示的文字也是一个比较重要的议题。不像桌面PC,日常使用中只需要一种语言。当然,对于嵌入式设备,平时确实也只是一种,但这只是对于用户而言;如果对于开发者,则必须考虑到多种语言如何方便性地共存。最典型的例子便是手机,普遍性地说,手机的系统语言都会有英文,简体中文和繁体中文选项。
       
       语言的切换其实很简单,关键在于方式的简便与否。
       
       最为笨拙的方法无非是直接采用switch方式:
       switch(language)
       {
         case EN:
          m_Info1.SetText(TEXT(""))
          break;
        case CHS:
          m_Info1.SetText(TEXT(""))
          break;
        case CHT:
          m_Info1.SetText(TEXT(""))
          break;
       }
       
       ....
       
       switch(language)
       {
         case EN:
          m_Info2.SetText(TEXT(""))
          break;
        case CHS:
          m_Info2.SetText(TEXT(""))
          break;
        case CHT:
          m_Info2.SetText(TEXT(""))
          break;
       }
       
       从代码中就可以很容易看见这种方式的弊端:每增加一个信息显示控件就必须增加一个switch语句块,每增加一个语言就必须要增加一个case语句。而对于嵌入式设备而言,增加新的控件和语言是常事,这弊端带来的结果就是不胜其烦的代码添加。更为严重的一个问题是,语言资源在代码编译阶段已经确定,如果是通过资源配置而达成文字的不同,则需要对源代码进行大量的更替。基于以上原因考虑,该方式为鸡肋。
       
       所以还是和图片方式一样,采用类封装的方式:

      namespace StrTab
      {
       enum Language
       {
        LANG_EN = 0x01,
        LANG_CHS,
        LANG_CHT
       };
       
       enum String
       { 
        STR_NONE,
        STR_INFO1,
        STR_INFO2,
      
          ....
       };
      }
      
      class CStrTabBase
      {
      public:
       void SetLanguage(StrTab::Language lang);
       virtual TSTRING GetString(StrTab::String strIndex);
      };

        采用类封装方式,之前通过switch语句更新资源的代码可以更改如下:
        CStrTabBase StrTab;
        
        ...
        
        //设置语言
        StrTab.SetLanguage(StrTab::LANG_CHS);
        
        ...
        
        //设置字符串
        m_Info1.SetText(StrTab.GetString(StrTab::STR_INFO1));            
        m_Info2.SetText(StrTab.GetString(StrTab::STR_INFO2));         
        
        这样的好处显而易见,语言只需要设置一次,然后文字设置可以避免采用大量的switch语句。还有另外一个不为人注意的好处是,字符串的设置只和CStrTabBase的GetString函数有联系,而不管其内部是如何获得的。也就是说,语言的资源即可以在编译时确定,也可以在运行时获取,但究竟采用何种方式,对于界面的字符串设置代码来说都是一致的,并不需要做任何更改。
        
        因为动态获取语言资源方式繁多,在此不再累赘,只是简单说说如何编译时期确定语言资源如何才能做到最简便。如果还是像之前采用switch块,则显得有点换汤不换药的味道。鉴于此,我们采用STL库的map。
        
        我们使用三个map变量,用来存储相应的语言资源:
        std::map<StrTab::String,TSTRING> mpChinesSimplified;
        mpChinesSimplified.insert(std::make_pair(StrTab::STR_TV,TEXT("移动电视")));
        m_mpString.insert(std::make_pair(StrTab::LANG_CHS,mpChinesSimplified));
        
        std::map<StrTab::String,TSTRING> mpChinesTraditional; 
        mpChinesTraditional.insert(std::make_pair(StrTab::STR_TV,TEXT("數位電視")));
        m_mpString.insert(std::make_pair(StrTab::LANG_CHT,mpChinesTraditional));
         
        std::map<StrTab::String,TSTRING> mpEnglish; 
        mpEnglish.insert(std::make_pair(StrTab::STR_TV,TEXT("TV")));
        m_mpString.insert(std::make_pair(StrTab::LANG_EN,mpEnglish));
        
        获取函数则可以非常简单:
        TSTRING CStrTabBase::GetString(StrTab::String strIndex)
        { 
         return (m_mpString[m_Lang])[strIndex];
        }
        
        以后当我们需要添加新的字符串资源时,只需要在初始化添加相应的字符串即可。这样不仅避免了大量的case语句,还能令代码条理清晰,方便简洁。
        
        细心的朋友可能发现,CImgTabBase和CStrTabBase有所不同。对于图片资源来说,不同的方案,表现的图片会不一样,比如说,同样代表“设置”的图标,可能给A公司和给B公司的完全不同(否则就撞车了);但文字资源,无论是A公司或是B公司,功能都叫“设置”。因此,图片类实际获取资源的是取决于子类,而文字资源则是基类。文字资源的子类,只是更改部分某些不同的数值而已。
        
        与此相对,一些常用的数值也可以先用类封装,方便之后的更改: 
        
        namespace ValTab
        {
         enum CtrlColor
         {
          COLOR_TXT_ITEM,
          COLOR_TXT_WND_TITLE,
          ...
         };
        
        
         enum CtrlSize
         {
          TXT_ITEM_WEIGHT,
          TXT_ITEM_POINT_SIZE,
            ...
         };
        
        }
        
        class CValTabBase
        {
        public:
         virtual COLORREF GetColor(ValTab::CtrlColor ctrlColor);
         virtual DWORD GetSize(ValTab::CtrlSize ctrlSize);
        
        };
        
        类似于此,很多随着环境会改变的数值,按钮的位置等等,都可以采用此形式封装。
        
        如果全部采用封装形式,每次添加新值只需要在初始化中添加相应的数值即可:

        BOOL CMainCtrl::Initialize(HINSTANCE hInstance)
        { 
         switch(m_Option.GetImgTab())
         {
          case Option::IMG_A:
           m_pImgTab = new CImageTabA(); 
           break;
          case Option::IMG_B:
           m_pImgTab = new CImageTabB(); 
           break;
          
           ...
           
          //如果有新值,在这里添加
          
           ...
          
          default:
           m_pImgTab = new CImageTabA(); 
           break;
         }
        
         switch(m_Option.GetPosTab())
         {
          case Option::POS_A:
           m_pPosTab = new CPosTabA();
           break;
          case Option::POS_B:
           m_pPosTab = new CPosTabB();
           break;
          
           ...
           
          //如果有新值,在这里添加
          
           ...
          
          default:
           m_pPosTab = new CPosTabA();
           break;
         }
        
         switch(m_Option.GetValTab())
         {
          case Option::VAL_A:
           m_pValTab = new CValTabA();
           break;
          case Option::VAL_B:
           m_pValTab = new CValTabB();
           break;
          
           ...
           
          //如果有新值,在这里添加
          
           ...
          
          default:
           m_pValTab = new CValTabA();
           break;
         }
        
         switch(m_Option.GetStrTab())
         {
          case Option::STR_A:
           m_pStrTab = new CStrTabA();
           break;
          case Option::STR_B:
           m_pStrTab = new CStrTabB();
           break;
          
           ...
           
          //如果有新值,在这里添加
          
           ...
          
          default:
           m_pStrTab = new CStrTabA();
           break;
         }
         m_pStrTab->SetLanguage(m_Option.GetLanguage());
        
        
         return TRUE;
        }

        万变不离其宗,对于windows程序而言,最主要的还是窗口。很多时候,大家常用的做法是一个界面,就写一个源代码文件。这样当然简单,但带来的问题就是代码重复度高,没增加一个窗口就要增加一个文件,显得很累赘。所以,关于窗口,我们是采用只用一个窗口类,通过设置不同的数值,来生成形式各异的界面。
        
        我们先来分析一下像这种简单UI程序不同界面的区别。一般来说,像界面无非是有如下控件:
        
        1.按钮:用来实现特定功能
        
        2.文本:用来显示不同的文字
        
        3.进度条:用来显示某些特殊功能的状态
        
        4.背景:窗口的背景图片。
        
        这四点,便是界面的共通点。所以我们在设计窗口类时,给这四点留出接口即可:
        
        class CUserWnd
        {
        public:
         BOOL SetButtonInfo(const std::vector<UserData::ButtonInfo> &vtBtnInfo);
         BOOL SetTextInfo(const std::vector<UserData::TextInfo> &vtTxtInfo); 
         BOOL SetProgressInfo(const std::vector<CProgress> &vtPrgInfo);
         BOOL SetBackground(UserData::BackgroundInfo bkInfo); 
          
          ...
        }
        
        然后对于不同功能的界面,我们只需要设置不同的数值即可:
        
        //背光窗口
        pWndBacklight->SetButtonInfo(vtBtnInfo1);
        pWndBacklight->SetTextInfo(vtTxtInfo1);
        pWndBacklight->SetBackground(bkInfo1);
        
        //电池窗口
        pWndBattery->SetButtonInfo(vtBtnInfo2);
        pWndBattery->SetTextInfo(vtTxtInfo2);
        pWndBattery->SetBackground(bkInfo2);
        
        这样我们只需要一个窗口类,就能实现变化各异的界面。
        
        在这里还有一点需要提一下,一般来说,我们显示界面和功能的实现应该分开,这样代码看起来就不会变得杂乱无章。我们可以采用这么一种做法,定义一个CCommand类,主要是执行按钮的相关功能操作,然后窗口类继承于该类即可:
        
        class CCommand
        {
        protected:  
         BOOL ExecuteCmd(UserData::CtrlIndex ctrlIndex,DWORD dwParam);
         
         ....
         
        }
        
        BOOL CCommand::ExecuteCmd(UserData::CtrlIndex ctrlIndex,DWORD dwParam)
        {
         switch(ctrlIndex)
         {   
          case UserData::BTN_EXIT:
          {
           return OnCmdExit();
          }
          case UserData::BTN_EXPLORER:
          {
           //Execute the explorer and then exit the application
           CCommon::Execute(m_Option.GetPathTab(Option::PATH_EXPLORER).c_str());
          }
          
          ...
          
         }
        }
        
        //窗口的继承
        class CUserWnd:
         public CCommand
        {
          ...
        }
        
        基本上,嵌入式UI架构的设计如此了。其实,只要能做到界面更换简单,功能添加简便,基本上往后的工作就会非常容易,所以初始的架构设计就显得非常重要了。
        
        
        
        后记:好久没写这种纯理论到连自己看了也觉得不知所云的东西了...文中的代码是从我所写的工程中搬出来的,直接用到别的地方肯定是行不通,所以大家仅仅是看看,做做参考就好。:-)

    18/04/2009

    整晚的失眠

    失眠...对于我来说挺遥远的,特别是因为情感问题!但是,昨天我失眠了,失得很彻底,很窝囊!我努力的寻找着我该处在的位置,我找不到...为什么我苦苦寻求的简单的生活方式却又要有这样的事情发生呢?到底是谁在耍我?

    07/04/2009

    本命年伊始:心烦意乱

    一年的时间很快过去,本命年到来了,强迫我的妹妹买了根红绳给我挂着...我妹妹问:哥,你还信这个啊?我心里默默的说:我索要的是祝福,不是迷信。所以我回家了。这一年的时间里,我越来越感觉到亲情的重要了,我工作和生活的绝大部分动力都来自于我的家庭。朋友见面的时间越来越少了,言语之间,话题在变,但还是很开心。

    今年年过得很开心,参加了同学的婚礼,见到了所有我想见的人。大家都有所改变,但是聊天时还不乏校园的一种稚气,只是越来越模糊了!不知道为什么,这些年来,想到同学的时候心里总是有一些伤感,总是再回忆过去。大家的生活渐行渐远,也不止大家是否一如既往的开心。

    就先写一点吧,其实也不知道该写些什么,也许是我自己太感伤了!

    21/06/2008

    生病

             真的很奇怪,想来已提出离职就感冒。

    离忆

              想起那些日子,不能回忆的是高考后的心理压力,同时还有的就是离别的痛苦,也让我不能自拔了好长一段的时间。但是,有段回忆却是彩色的,暂且叫它离忆吧。

    25/05/2008

    辞职

              关于辞职,我已经想过很久了。从3月底部门架构重组后到现在,思考的时间也差不多历时一个月了。前天从公司的一大堆通告、表格中找到了《员工辞职申请表》,下定决心离职!

              这是我的第一份工作,在即将离别之际,我不由的想起初由学校来深圳那些日子。毕业之处的茫然挂在每个人的脸上,当时的我们不断的宣泄着离别带来的痛苦,亦或是自我麻痹——我们每天都去学校后门的网吧,玩着游戏、吃便宜炒饭、聊通宵的天。这是我们选择的对将逝去的校园生活的一种祭奠。这不是堕落,也不是发泄,是抵抗,是依赖。这是在表达感情,没有人能要求什么,改变什么。最后的这段时光,随着分别的日子,随风飘走。走的那天,我清晰记得的眼泪也散落在了视野之外。这是我的追忆!

              依稀记得在学校门口和涛的一段对话。

              涛:毕业了有什么打算?

              我:不知道,想还是想做网络方面的吧。你呢?

              涛:我还是在南昌这边,先做段时间,看看朋友们那边怎么样。

              我:朋友那边,做什么?

              涛:我们家那边很多做铝合金生意的,他们比我早出来,现在已经很不错了,可能会先跟着他们混。

              我:哦,我还是那个想法,想做3G方面的东西,找个这方面的工作吧。

              涛:恩,你还是可以的,努力去做啊!

              我:恩,一起加油。

              这其中其实已经是最简陋的一个“职业规划”了,我们都有各自的想法。不知道涛哥现在还记不记得,我一直都记得。这样的交流在同学们之间都很多,我知道,但很模糊。这想法随着我的旅程也到了深圳,在这城市的第四天便去书城买了《移动通信类职位应聘指南》这本书,虽然其中的内容大多跟我的专业相差比较远,但是我看到移动通信产业链中sp这一块,这是我为之兴奋的一点。随后,我开始跑人才市场、投简历、面试,然后循环这一过程,我逐渐适应,但是慢慢的忘却了想法。就业——是我那个时候的必要任务。当时的日子我想众众应该印象深刻,这里我不想说,以后再写吧!

               我想天道酬勤是不会错的,一面、笔试、二面一路pass第一份工作就找到了,而且一干就是一年。这一年工作中的心态也经历了几种转变。重一开始的充满激情,到对工作出现不满,一直到现在发现我真的不适合做着份工作,我开始了新的思考。这段时间以来,我一直在回溯我的记忆,找寻着自我。在大学里,都在摸索着,但是现在怎么就不对劲呢?一句话无意中点醒了我——知之者不如好之者,好之者不如乐之者。我的兴趣不在这里,我的工作不应该是那些,辞职!

               最近,阿甘这边沟通也很多,他的想法要稍多些,我毕竟不在这个行当里,想法自然少些。但是我们对我们的目标少了些激情,我不认为这是件坏事,至少我们现在都理智了很多。对待一些已有的想法也更趋于实际。但我还是担心的,因为他说过我们不能共事,说实话,我一直都猜不透这句话。这次我回南昌为的就是这个事情!

               兄弟们,记得自己曾经想要的,去追求吧,厚积薄发!

    04/05/2008

    忍者神龟

            昨天我看了07年上映的美国动画片《忍者神龟》。其实,这部电影我早就想看了,只是当时上映的时间正好是我毕业的时间,没有时间去看。想看这部影片的初衷很简单,小时候我们经常玩这个游戏,所以有点怀旧的味道在里面。

           这次看感觉还不错,也找到了我应有的回忆。惯使武士刀的“蓝霹雳”莱昂纳多、手持木棒的“爱因斯坦”多纳泰罗、暗藏忍者匕首的“火爆红”拉斐尔和双节棍舞得虎虎有声的“掉链子”米开朗琪罗,利落身手和聪明头脑比任何超级英雄都毫不逊色的小龟们,个个都是个性十足、忍者功夫精到的全能高手。

                                         忍者神龟

           除此之外,我也还发现不少的东西。莱昂与拉斐尔之间的矛盾体现了真正的友谊、四兄弟的并肩作战体现了什么是团队精神、忍者的修炼之路体现了什么是奋斗。这些都是在现实中不那么清晰的东西。其中的人物性格刻画我也十分喜欢,莱昂的自负、多纳泰罗的责任心、米开朗琪罗真实的自我和拉斐尔的执着都是让我心生共鸣的地方。

                                         莱昂

            如此性格迥异的四只乌龟却能为了一个共同的目标而团结再一起,进而去做自己想做的事情,这是让我感动的地方。鼠老大说:“你的兄弟都有优点和弱点,当他们处于弱势时你就应强大起来,如果你不能认识到这个,那么这个家没有希望..”,这句话让我感觉到什么是真正的兄弟。是的,我也有我的兄弟,我们也有着共同的理想,但是我们有点在生活中迷失了自我,正如影片开始的时候那样。记住自己心中所想的,如拉斐尔一样的执着,我想是会有再聚在一起的一天的!我们都在修炼,蓄势待发!

                                         四兄弟

    01/05/2008

    间断性思维

           这个词是在上班的时候突然想到的,想到了就记下来了。其实我想这个词是最能表达我这段时间以来做事的一个方式了。

           很多的时候,我的思维和我行为完全的脱离开来了。而思维一直都是断断续续的分散在行为中间,一段一段的......我想这个就是我对待生活比较疲软的原因吧!清晰的思路常常出现在起床去上班的时候、中午休息的时候和晚上躺在床上的时候,这个时候我才想着我最想要的是什么,我所追求的是什么。但是,一旦我进入到工作中,甚至是娱乐中,我会忘记那些我所想!我不知道我这是为什么,我想我是害怕了,害怕这些太遥远,不是我现在的生活所能够给予的,正如我害怕开始一样。想变......

           我想,我乱......

           不止一次的朋友和我谈起关于职业的方向选择的事,我想我是有一个坚定的立场的,我想。这些思路也在我的脑海里以间断性的思维不断的出现,我是相信我仍然相信的,我是要回到我的兴趣所在的。而我这段时间以来,很多羁绊,社会经验不丰富也好、职场经验不足也好、经济条件制约也好、自己害怕也好,我想我是习惯这些了。

    21/04/2008

    状态

          一直都在关注却未改变过的东西,这是我对我目前的状态下的一个定义。

    恍惚的思念

              天气莫名其妙的好,心情也跟着很好。太阳射进窗户的那一刹那,我还静静的躺在床上,很舒服,很温暖!躺在窗上静静的回忆的,思绪断断续续。冬天深圳的阳光难得有这样的柔和的,让我想起了在学校。工作就是这样,让人忘却的东西太多了,你的激情,你的精力,你所在乎的东西都在一点一点的消失,患得患失!
    22/04/2007

    在百度的日子里

        时间过得真的挺快的`等我想起来这里写点什么的时候,我已经身在深圳了``也许决定来深圳的理由很简单-IT公司多达1650多家,俗话说瘦死的骆驼比马大,所以我就来了``但是我的决定是没有错的,深圳是一个移民城市,不象北京、上海存在“歧视”问题。而且深圳是经济特区,一个在高度发展中的城市,对我来说这是一个不错的选择。
        刚下火车那会,并没有意料中的那种激动与兴奋,相反的是心情极度的平静。也许,是因为我没有怀着一个大的目标,一个远大的理想才来到这个城市的关系吧,我只想在这样一个拥挤的城市里找到一个属于我空间。我量力而行。
        心情上的平静不能取代随之而来的焦虑与紧张,因为一切都是这样的陌生,这样的不可控制。我努力的去调整自己的心态,不断的给自己鼓励,希望自己能有一个好的开始。在众众的表姐家呆了两天后,我转住到了我叔叔家,那边离人才市场会更近一些,这样我不用每天的就这样的来回的跑了。准备好了行头之后(所谓的行头就衬衫、西裤和皮鞋  注:皮鞋被宰花了275心痛啊~~),便开始跑人才市场了。
        初八一大早,我和众众带着上个世纪的简历冲到了人才大市场,脑袋一片空白。在这样一个拥挤不堪,人头篡动的空间里,我感觉到了竞争。
    五元一张门票这样的现场招聘会天天都有,但是好象找工作的永远比提供的岗位多得多。
    14/12/2006

        今天算是忙了一天了,为了画一个系统结构图上网兜了一圈,想找一个专业的工具来描述一个系统。开始,我想到的是UML,可是OOD中没有系统结构图这个概念,而且UML中的视图(view)是对软件系统进行面对对象的描述和建模,而我是想通过系统分析建立一个系统的物理模型,类似系统的数据流图中的顶层图,通过这个图来对系统做个简要的描述。遍历了baidu之后,我发现了一个工具-Microsoft Office Visio 2007 -他是一款商用和科技图表制作程序,应用的范围很广,从家居规划到工程制图,从各种软件和数据库视图到商务的工作流程图甚至是营销图标,可以说是囊括所有的商业应用图表。下载...安装...打开来,没有我需要的系统结构图,但是研究了一会之后发现,它里面给出视图都是以模板的形式给出的,也就是说你可以创建自己需要的图表,嘿嘿,开工了```为了节省时间,我用了程序结构图做为模板进行绘制的。我所要描述的是一个搜索引擎系统,下面就是它的系统结构图了:
     
         简要的说明一下,系统分为两个部分:
            1. Front-end process
            2. Back-end  process  

         前端用来处理用户的查询请求,后台用来对用户的请求做出分析,然后在Index Files中查找到相应的数据对数据做出排序,再把结果返回给用户,整个图是按照数据流来绘制的。

         通过这个图的绘制,个人感觉visio还是一个不错的软件,它能够很好的诠释你的想法,过程和系统,让你更好的完成整个系统的设计与分析。

    10/12/2006

    在台灯下度过的日子

          嗯...扳手指头一算,这个星期来已经通宵了4,5天了,白天几乎都是在睡眠中度过的,晚上陪伴我的就只有我那盏小台灯了。在这样阴冷的天气里,有一个功率40w的取暖器还真的挺舒服的,而且我也很喜欢它泛出的那种柔和的黄光,让我有一种思念的感觉,孤独而又温暖。
         最近一段时间都在"忙"着写论文,为什么要打双引号呢!这个我身边的人都知道,这个忙是要打折扣的。譬如,有人问你:嗨!最近在忙什么呢? 这个时候在你的大脑里浮现的肯定是对你,或者是对你的生活起着促进作用的事情,而现在我唯一要做的也就是好好的把毕业论文给写完了。(至于什么好好学习,天天向上之类的都是些后话了,在很长一段时间内我根本都不想提及这些)。
        提及论文还真有些话是要说的。先说说给我们安排论文分组的计算机系秘书吧。丫就是一噱头,论文按你的姓氏来分组,根本不顾及你的专业方向和本人的意向,很不幸的我(网络模块)被分到了一个研究软件的小组里了,课题也和我的网络一点关系也没有,完全就是软件领域的课题。当我很气愤地跑到系办公室抗议:这不公平!教学秘书一句话:“你觉得这个社会什么对你来说才是公平的呢?”顿时,我无言以对。

    基于JDK1.5.0+tomcat5.0+Eclipse3.2.1的web应用程序开发平台的搭建

          最近由于论文的需要,所以要搭建一个web应用程序的开发环境,程序采用java进行开发,所以下面对整个应用程序的开发环境的配置做个介绍:
     
         1. JDK1.5(Java Development Kit)
     
         这是SUN公司的一个开发工具集,它为java提供了一个丰富的语言和运行环境,开发人员和最终用户都可以利用这个工具来开发java程序。
        
     
         下载完成后开始安装JDK1.5,下载下来的是一个安装文件,双击它就可以安装,安装过程比较简单基本上一路next就可以了,不过要注意下你的安装目录还有你所使用的浏览器。之后会要求你重起系统,这里建议先不要同意,等JDK的环境变量配置完成后再重新启动计算机。
     
         JDK配置:
              1. 用鼠标右键单击桌面上的我的电脑,在弹出的快捷菜单中选择“属性”选项。(这里我就不贴图了,麻烦 -_-! 我尽量写详细些吧)
              2. 在弹出的“系统属性”中选择“高级”选项卡中的“环境变量”按钮,弹出“环境变量”对话框。
     
              3. 单击“系统变量”区域中的新建按钮,在弹出的“新建系统变量”对话框中,添加如下环境变量 (假定JDK安装在D:\java\jdk1.5.0)
                         变量名: CLASSPATH
                         变量值: D:\Java\jdk1.5.0\;D:\Java\jdk1.5.0\lib\tools.jar;D:\Java\jdk1.5.0\lib\dt.jar;D:\Java\jdk1.5.0\bin
     
              4. 选中“系统变量”区域中的Path变量,在弹出的“编辑系统变量”对话框中为path变量,追加如下变量值:
                         变量名: PATH
                         变量值: D:\Java\jdk1.5.0\bin\
                           
         配置完成后,重新启动计算机,ok~ JDK配置完毕。
     
         2. Tomcat5.0
     
         Tomcat是Apache Group Jakarta 小组开发的支持JSP和Servlet的免费服务器软件。
     
     
          tomcat的安装比较简单,一路next就ok了,需要注意的是tomcat服务的启动需要jdk,因为tomcat本身就是用java编写的程序,所以程序的运行就需要java解释器。
     
          tomcat配置:
               1. 安装Tomcat后,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的tomcat安装在c:\tomcat):
      
            CATALINA_HOME=c:\tomcat
            CATALINA_BASE=c:\tomcat
      
            2. 然后修改环境变量中的classpath,把tomat安装目录下的common\lib下的(可以根据实际追加)servlet.jar追加到classpath中去,修改后的classpath如下 (%JAVA_HOME%指的是JDK的安装目录):
      
            classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\common\lib\servlet.jar;
      
            3. 接着可以启动tomcat,在IE中访问http://localhost:8080,如果看到tomcat的欢迎页面的话说明安装成功了。
         
          3. Eclipse
        
         Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括 Java 开发工具(Java Development Tools,JDT)。
     
          下载地址:http://www.eclipse.org/downloads
     
          下载下来的将是一个压缩包,解压之后就可以运行了,不需要安装。
     
          从eclipse官方网站下载的只带有基本的几个插件,如果要多种J2EE的元素、Web应用的开发和最流行的应用服务器结合为一体就要向eclipse中添加插件,现在网上这样的插件有很多,这里我推荐使用lomboz(它Eclipse的一个主要的开源插件(open-source plug-in),Lomboz插件能够使Java开发者更好的使用Eclipse去创建,调试和部署一个100%基于J2EEJava应用服务器。)
     
        至于如何向eclipse中添加lomboz这样的文章网上有很多,稍微baidu一下就可以找到答案了,我就不在这里敖述了。这里我要介绍一个IBM的Callisto Simultaneous Release project,这个是IBM的一个developerWorks,它提供了带有集成开发环境插件包的eclips它们分别是:
          • Web Tools Platform (WTP)
          • Graphical Modeling Framework (GMF)
          • Test and Performance Tools Platform (TPTP)

        其中第一项就是关于web应用程序开发的,我们可以下载,地址是:http://www-128.ibm.com/developerworks/eclipse。这其中已经包括了web应用程序的开发环境了,不用进行任何多余的配置了,挺爽的,功能比Lomboz还要多些。 (o.O 呵呵,走了一条捷径~~)

        这样一个基于JDK1.5.0+Tomcat5.0+Eclipse3.2.1的web应用程序开发平台基本上就搭建完毕了,呼呼~~~~

    一 搜索引擎的技术原理

          信息时代带来的信息爆炸,可能您已经想像不到现在的Internet上到底有多少信息,又有多少信息正在产生并且上传到这个网络中。仅仅依赖于人类自身生理范围内的检索能力在互联网中查找信息,我们几乎等同于生活中的盲人,无所适从。不断发展的数据收集、数据结构、数据存储、数据检索以及等等若干技术因素催生了搜索引擎这个“网络精灵”的出现。


          搜索引擎,Search engines,又称搜索机,Web搜索器,是伴随WWW网络出现的检索网上信息资源的新工具。实质上是一种网页网址检索系统,有的提供分类和关键词检索途径,有的仅提供关键词检索途径。它根据检索规则和从其他信息服务器上得到数据并对数据进行加工处理,自动建立索引,并通过检索接口为用户提供信息查询服务,能够自动对WWW资源建立索引或进行主题分类,并通过查询语法为用户返回匹配资源的系统。搜索引擎主要是由Crawler、Spider、Worm、Robot等计算机软件程序自动在因特网上漫游,不断搜集各类新网址及网页,形成数以千万甚至上亿条记录的数据库。它是通过采集标引众多网络站点来提供全局性网络资源控制与检索机制、将全球WWW网络中所有信息资源作一完整的集合、整理和分类、方便用户查找所需信息的网络检索软件。具有检索面广、信息量大、信息更新速度快,特定主题的检索专指性强等特点。


          说起来容易,可是搜索引擎其技术细节却如“塘中荷”,远观很美,近其身却很难。难就难在它要面对的是海量的、或者说是无限膨胀中的数据,它要提供的是高效的、与当前快节奏生活合拍的服务,它依托的又是当前最新的、最前沿的技术。自然而然,它在发挥其不可替代的信息检索作用的同时,也成为很多商家在商界驰骋的筹码,从而又戴上了一层神秘的面纱。笔者毕业设计的目的是研究搜索引擎技术实现,限于技术能力与时间,可能并未得其真髓,但至少也希望可以拨开几片荷叶,可以对搜索引擎这朵美丽的“荷花”有更加清晰透彻的认识。