国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

采用敏捷方法進(jìn)行用戶(hù)界面開(kāi)發(fā)

2019-11-18 12:16:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  摘要
  
  1991年秋,在美國(guó)勒海大學(xué)亞科卡學(xué)院的一份研究報(bào)告《21世紀(jì)美國(guó)制造業(yè)的戰(zhàn)略:一個(gè)工業(yè)主導(dǎo)的觀點(diǎn)》中,首次提出了靈敏競(jìng)爭(zhēng)的概念.而今天,我們似乎已經(jīng)看到,靈敏已經(jīng)在我們身邊,形影不離.
  
  之前Matrix一則討論激烈的新聞(http://www.matrix.org.cn/resource/news/314_Agile.Html), 也表達(dá)了靈敏在今天的熱度.下面通過(guò)一個(gè)簡(jiǎn)單的例子, 告訴你如何起步靈敏開(kāi)發(fā)..
  
  概述
  
  假如你沒(méi)有采用靈敏的方式,那你就落后了。這是最近SD Best PRactices 2004會(huì)議上的標(biāo)語(yǔ)。靈敏的方法就象XP和Scrum正在世界的軟件發(fā)展中,變得越來(lái)越普遍了。靈敏是一個(gè)巨大的改變,讓軟件開(kāi)發(fā)者把重心轉(zhuǎn)移到質(zhì)量和速度上。這對(duì)已經(jīng)被比喻成面向?qū)ο笤O(shè)計(jì)的軟件開(kāi)發(fā)有很大的影響。但是,這種影響的一些方面已經(jīng)放慢了:GUI的開(kāi)發(fā),自從大多數(shù)軟件包含了一些類(lèi)型的GUI,而且比較多的軟件開(kāi)發(fā)的百分比是去完成以GUI為中心的,應(yīng)用靈敏的優(yōu)勢(shì)去開(kāi)發(fā)GUI就是要害問(wèn)題了。
  
  什么在阻止人們用靈敏的方法來(lái)開(kāi)發(fā)GUI呢?不論他們的應(yīng)用是基于web的或是桌面應(yīng)用,大多數(shù)開(kāi)發(fā)者不做用戶(hù)界面user interface的測(cè)試驅(qū)動(dòng)開(kāi)發(fā)test-driven development (TDD)。這都因?yàn)橐粋€(gè)簡(jiǎn)單的原因:?jiǎn)卧獪y(cè)試GUI是很困難的。測(cè)試GUI是很乏味沉悶而且輕易出錯(cuò)的,包含了模擬用戶(hù)事件的復(fù)雜代碼,在事件傳播和控制重繪的時(shí)候等待,然后在他顯示給用戶(hù)之前,嘗試著檢測(cè)狀態(tài)。靈敏依靠于測(cè)試驅(qū)動(dòng)開(kāi)發(fā),但是為GUI的特定行為來(lái)寫(xiě)有效的測(cè)試代碼是困難的。在cube farm(辦公農(nóng)莊,用隔斷間隔成很多小工作間的辦公室? 商務(wù)英語(yǔ))的GUI方面上,質(zhì)量和設(shè)計(jì)從靈敏方法中受益已經(jīng)被完全熟悉到。
  
  靈敏實(shí)踐正在滲透進(jìn)這個(gè)領(lǐng)域。單元測(cè)試GUI元素的工具激增,JFCUnit 框架測(cè)試GUI是用java Swing,基于Web的GUI能被HTMLUnit, HTTPUnit, jWebUnit和類(lèi)似的工具測(cè)試。許多GUI構(gòu)造器和工具包和單元測(cè)試工具有關(guān)系,比如VBUnit是為了Visual Basic,QtUnit是給Qt用的。
  
  工具已經(jīng)存在了,但是處理仍是不確定的。在測(cè)試驅(qū)動(dòng)開(kāi)發(fā)(TDD)中,每個(gè)代碼的改變都在新行為的單元測(cè)試前。在開(kāi)發(fā)GUI時(shí),許多變化不過(guò)是視覺(jué)顯示上的調(diào)整,比如改變?cè)氐奈恢茫谋荆蛘哳伾D憧梢约右粋€(gè)按鈕,建一個(gè)菜單項(xiàng),或者構(gòu)造一個(gè)對(duì)話框。但是怎樣和為什么你要測(cè)試這種變化呢?測(cè)試每個(gè)標(biāo)簽或者顏色值是很愚蠢的。同樣的,對(duì)于標(biāo)準(zhǔn)的元素象按鈕和域,測(cè)試他們通常的行為是沒(méi)有意義的,象對(duì)鼠標(biāo)移動(dòng)的響應(yīng),鍵的按下,點(diǎn)擊,和諸如此類(lèi)的。這些事情是不可能被中斷的。怎樣去測(cè)試他們的問(wèn)題只是徒勞的增添了做GUI測(cè)試的難度。
  
  一個(gè)要害的問(wèn)題:怎樣做測(cè)試先行的開(kāi)發(fā)?答案就在于GUI的編碼是怎樣組織的。靈敏方式的領(lǐng)袖例如Kent Beck 和 David Astels建議在構(gòu)造GUI的時(shí)候要保持視圖對(duì)象盡可能是輕量的,而且“在表面下”( below the surface.)測(cè)試視圖層。這個(gè) 靈敏對(duì)象/瘦視圖 模型和我們熟悉的 文檔-視圖 及 客戶(hù)端-服務(wù)器模式類(lèi)似,但是被應(yīng)用于個(gè)別的GUI元素。內(nèi)容和表現(xiàn)的分離改善了代碼的設(shè)計(jì),使他更模塊化和更利于測(cè)試。每個(gè)用戶(hù)界面的組件被實(shí)現(xiàn)為一個(gè)靈敏對(duì)象,包括將要被測(cè)試的應(yīng)用的行為,但不包括GUI表現(xiàn)的代碼。每個(gè)靈敏對(duì)象有一個(gè)相應(yīng)的瘦視圖類(lèi)只包括普通的GUI行為。采用這種設(shè)計(jì)模式,GUI構(gòu)造變得可以被應(yīng)用于 測(cè)試驅(qū)動(dòng)開(kāi)發(fā)(TDD) 處理了。
  
  例子:構(gòu)造一個(gè)登錄對(duì)話框
  
  讓我們進(jìn)入一個(gè)例子看看怎樣使用TDD和 靈敏對(duì)象/瘦視圖 代碼設(shè)計(jì)模式去開(kāi)發(fā)一個(gè)GUI對(duì)話框。起初,讓我們考慮對(duì)話框的圖形,靈敏開(kāi)發(fā)提倡預(yù)先最小化設(shè)計(jì),讓軟件構(gòu)架在多次循環(huán)開(kāi)發(fā)中重構(gòu),但是這個(gè)方法對(duì)GUI設(shè)計(jì)不是很合適。設(shè)計(jì)一個(gè)用戶(hù)界面是一個(gè)創(chuàng)造的過(guò)程,應(yīng)該規(guī)范地處理,畫(huà)草圖,做原型,和可用性測(cè)試。然后,盡管在GUI下的代碼可以用TDD迭代地設(shè)計(jì),一個(gè)形象的設(shè)計(jì)草圖是明智的第一步。這個(gè)對(duì)話框的基本的設(shè)計(jì)在圖1中勾畫(huà)出來(lái)。
  
  
 采用靈敏方法進(jìn)行用戶(hù)界面開(kāi)發(fā)(圖一)
  Figure 1. GUI design sketch for login dialog

  
  這個(gè)對(duì)話框很簡(jiǎn)單,包括用戶(hù)名和密碼域,相應(yīng)的靜態(tài)文本框和標(biāo)簽,登錄和取消按鈕。做為一個(gè)他行為的初始輪廓,我們決定登錄成功的話對(duì)話框關(guān)閉,登錄失敗的話對(duì)話框仍然開(kāi)著。取消按鈕也關(guān)閉對(duì)話框。
  
  基本的 靈敏對(duì)象/瘦視圖 代碼類(lèi)設(shè)計(jì)的對(duì)話框?qū)崿F(xiàn)在圖2中表示。
  
  
 采用靈敏方法進(jìn)行用戶(hù)界面開(kāi)發(fā)(圖二)
  Figure 2. The classes LoginDialog and LoginDialogView

  
  靈敏對(duì)象類(lèi)LoginDialog 將包含一個(gè)方法對(duì)應(yīng)對(duì)話框的每個(gè)功能行為。瘦視圖類(lèi)LoginDialogView 將只包含簡(jiǎn)單的和顯示相關(guān)的代碼,還有g(shù)et/set 方法去讀取和設(shè)置顯示的信息。在這個(gè)過(guò)程里,只有LoginDialog里復(fù)雜的功能需要被單元測(cè)試。我們可以十分自信在LoginDialogView 里的簡(jiǎn)單行為可以正常工作。
  
  第一個(gè)構(gòu)造的組件是靈敏對(duì)象LoginDialog 。他需要一個(gè)相應(yīng)的測(cè)試類(lèi)LoginDialogTest 。第一個(gè)測(cè)試方法將要驗(yàn)證登錄方法,如圖3所示。
  
  
 采用靈敏方法進(jìn)行用戶(hù)界面開(kāi)發(fā)(圖三)
  Figure 3. The smart object LoginDialog and its test class LoginDialogTest
  

  作為測(cè)試先行的開(kāi)發(fā)方法規(guī)定,首先要寫(xiě)單元測(cè)試。測(cè)試預(yù)期和定義了要被測(cè)試的功能設(shè)計(jì)。我們需要獲得一個(gè)用戶(hù)名和密碼,然后返回一個(gè)登錄成功或者登錄失敗。一個(gè)用來(lái)判定的接口方法來(lái)做剛才所述的
  
  boolean login(String username, String passWord);
  
  測(cè)試類(lèi)LoginDialogTest 將測(cè)試這個(gè)功能。例1展示了在LoginDialogTest.java. 文件中他的初始實(shí)現(xiàn)。
  
  LoginDialogTest.java
  
  import junit.framework.*;
  public class LoginDialogTest extends TestCase {
  public void testLogin() {
  LoginDialog dialog = new LoginDialog();
  assertTrue( dialog.login("user", "passwd") );
  }}
  
  這個(gè)測(cè)試是基于JUnit基礎(chǔ)測(cè)試類(lèi)TestCase的。測(cè)試方法testLogin()創(chuàng)建了一個(gè)LoginDialog 的實(shí)例,調(diào)用了他的login()方法,然后判定結(jié)果是真。這段代碼將不會(huì)編譯,因?yàn)長(zhǎng)oginDialog 不存在。在TDD過(guò)程后,LoginDialog
  
  將生成和保存,代碼編譯后,測(cè)試運(yùn)行驗(yàn)證將象預(yù)期的那樣失敗(因?yàn)榉椒](méi)有實(shí)現(xiàn))。然后 LoginDialog 為了通過(guò)單元測(cè)試給出最小的實(shí)現(xiàn),遵照靈敏的圣條 做 可能工作的最簡(jiǎn)單的事情(the simplest thing that could possibly work)。例2展示了最初的LoginDialog 版本,用最少的代碼通過(guò)了單元測(cè)試,實(shí)現(xiàn)在LoginDialog.java. 文件里。
  
  LoginDialog.java
  
  public class LoginDialog {
  LoginDialog() {}
  public boolean login(String username, String password) {
  return true;  } }
  
  使用下面的命令來(lái)運(yùn)行代碼
  javac -classpath ".;junit.jar" LoginDialogTest.java
  javac -classpath "." LoginDialog.java
  
  classpath 必須包括junit.jar 來(lái)運(yùn)行單元測(cè)試,因?yàn)樗褂昧薐Unit.在linux,Mac OSX,還有其他的UNIX系統(tǒng)上,classpath將包含一個(gè)冒號(hào)(:)而不是想下面那樣用一個(gè)分號(hào)。
  
  測(cè)試將如下運(yùn)行
  
  java -classpath ".;junit.jar" junit.textui.TestRunner LoginDialogTest
  
  單元測(cè)試通過(guò)了,真好!不幸的是,這個(gè)編碼只是模擬一下。Login()方法將總是批準(zhǔn)登錄。毋庸置疑,客戶(hù)將不會(huì)欣賞這種水平的安全機(jī)制。顯然,要寫(xiě)的下一個(gè)測(cè)試是驗(yàn)證假如給的條件不正確的話將失敗。例3展示了LoginDialogTest 的第二個(gè)測(cè)試方法去實(shí)現(xiàn)這個(gè)目的,testLoginFail() 。既然兩個(gè)測(cè)試都使用一個(gè)LoginDialog 的實(shí)例,測(cè)試類(lèi)被重構(gòu)為在他的setUp() 方法里創(chuàng)建一個(gè)固定的測(cè)試用的LoginDialog。
  
  LoginDialogTest.java
  
  import junit.framework.*;
  public class LoginDialogTest extends TestCase {
  private LoginDialog dialog;
  public void setUp() {
  dialog = new LoginDialog();
  }
  public void testLogin() {
  assertTrue( dialog.login("user", "passwd") );
  }
  public void testLoginFail() {
  assertFalse( dialog.login("", "") );
  }}
  
  LoginDialog 必須得通過(guò)新的測(cè)試,不能在第一次測(cè)試的時(shí)候有失敗。TDD過(guò)程引導(dǎo)我們構(gòu)造我們需要的真正的功能,在用正確的用戶(hù)名和密碼登錄的時(shí)候,能成功登錄,假如不是,就失敗。例4展示了按此修改的LoginDialog
  
  LoginDialog.java
  
  public class LoginDialog {
  private String user = "user";
  private String passwd = "passwd";
  LoginDialog() {}
  public boolean login(String username, String password) {
  if (user.equals(username) && passwd.equals(password))
  return true;
  else
  return false;
  } }
  
  LoginDialog 現(xiàn)在能通過(guò)所有的測(cè)試。為此,他包括了符合成功登錄條件的用戶(hù)名和密碼域。顯然,這只是比第一個(gè)版本的安全性能稍微好一些。登錄代碼不應(yīng)該包含認(rèn)證的硬編碼!基于這點(diǎn),我們應(yīng)該引入一個(gè)單獨(dú)的類(lèi)來(lái)包含LoginDialog 用的驗(yàn)證用戶(hù)的登錄信息。然而,這個(gè)例子是關(guān)于GUI構(gòu)造的,那讓我們暫停這個(gè)不安全的登錄代碼,繼續(xù)GUI方面。
  
  現(xiàn)在,我們已經(jīng)建立了登錄功能,并用單元測(cè)試覆蓋了他,但沒(méi)有可視的GUI來(lái)顯示它。那下一步該做什么呢?對(duì)于已經(jīng)作的和測(cè)試的實(shí)際功能,在GUI方面做的是創(chuàng)建和顯示圖像元素,然后在適當(dāng)?shù)臅r(shí)候調(diào)用login()方法。這個(gè)功能是普通和輕易建立的,所以他不包含能中斷和需要單元測(cè)試的復(fù)雜行為。因此,當(dāng)建立GUI元素時(shí),我們不需要去做測(cè)試先行的開(kāi)發(fā)。例5展示了創(chuàng)建對(duì)話框窗口的Swing類(lèi)LoginDialogView ,他的實(shí)現(xiàn)在LoginDialogView.java.文件。
  
  LoginDialogView.java
  
  import java.awt.*;
  import java.awt.event.*;
  import javax.swing.*;
  public class LoginDialogView extends JFrame
  implements ActionListener {
  protected JTextField usernameField;
  protected JTextField passwordField;
  protected JButton loginButton;
  protected JButton cancelButton;
  private LoginDialog dialog;
  LoginDialogView(LoginDialog dlg) {
  super("Login");
  setSize(300, 140);
  dialog = dlg;
  addControls();
  loginButton.addActionListener( this );
  cancelButton.addActionListener( this );
  }
  public void actionPerformed(ActionEvent e) {
  String cmd = e.getActionCommand();
  if (cmd.equals("Login")
  && dialog.login(usernameField.getText(),
  passwordField.getText())) {
  hide();
  }
  }
  private void addControls() {
  Container contentPane = this.getContentPane();
  contentPane.setLayout(new GridBagLayout());
  GridBagConstraints c = new GridBagConstraints();
  JLabel label1 = new JLabel("Username:", Label.RIGHT);
  c.insets = new Insets(2, 2, 2, 2);
  c.gridx = 0;
  c.gridy = 0;
  contentPane.add(label1, c);
  usernameField = new JTextField("", 60);
  usernameField.setMinimumSize(new Dimension(180, 30));
  c.gridx = 1;
  contentPane.add(usernameField, c);
  JLabel label2 = new JLabel("Password:", Label.RIGHT);
  c.gridx = 0;
  c.gridy = 1;
  contentPane.add(label2, c);
  passwordField = new JTextField("", 60);
  passwordField.setMinimumSize(new Dimension(180, 30));
  c.gridx = 1;
  contentPane.add(passwordField, c);
  loginButton = new JButton("Login");
  c.gridx = 0;
  c.gridy = 2;
  contentPane.add(loginButton, c);
  cancelButton = new JButton("Cancel");
  c.gridx = 1;
  contentPane.add(cancelButton, c);
  }}
  
  LoginDialogView 包含了文本域,標(biāo)簽,和按鈕元素。除了普通的GUI行為外,他只是有一個(gè)簡(jiǎn)單的行為,被actionPerformed() 方法實(shí)現(xiàn)。這個(gè)行為就是當(dāng)?shù)卿洶粹o被點(diǎn)擊后,login()方法被調(diào)用。假如登錄成功,對(duì)話框就被所調(diào)用的hide()方法所關(guān)閉。
  
  為了調(diào)用login()函數(shù),在LoginDialogView 構(gòu)造器里需要接收一個(gè)LoginDialog實(shí)例。另外,他組裝了完整的GUI設(shè)置和事件處理代碼。大部分代碼在addControls() 里,他簡(jiǎn)單的創(chuàng)建和排版了窗體上的GUI元素。
  
  LoginDialogView 代碼示范了一個(gè)GUI瘦視圖元素怎樣被設(shè)計(jì)使它只包含普通的GUI代碼,而把重要的需要測(cè)試應(yīng)用的行為放到一個(gè)單獨(dú),可測(cè)試的靈敏對(duì)象中。
  
  LoginDialogView 只需要通過(guò)創(chuàng)建它來(lái)測(cè)試,察看他,從用戶(hù)的角度確認(rèn)它看起來(lái)和運(yùn)行起來(lái)象期望的那樣。例6展示了可執(zhí)行的類(lèi)APPMain,它創(chuàng)建了對(duì)話窗體來(lái)傳遞可用性測(cè)試(指的是傳遞loginDialog的實(shí)例)。
  
  AppMain.java
  
  public class AppMain {
  public static void main(String[] args) {
  AppMain app = new AppMain();
  }  public AppMain() {
  LoginDialog dialog = new LoginDialog();
  LoginDialogView view = new LoginDialogView(dialog);
  view.show();
  while (view.isVisible()) {
  try {
  Thread.currentThread().sleep(100);
  } catch(Exception x) {}
  }
  System.exit(0);
  }}
  
  AppMain 類(lèi)簡(jiǎn)單的創(chuàng)建一個(gè)LoginDialog 和LoginDialogView ,顯示視圖,休眠直到視圖關(guān)閉,然后退出。
  
  AppMain 象下面一樣運(yùn)行
  
  java –classpath "." AppMain
  
  運(yùn)行它創(chuàng)建登錄對(duì)話框,如圖4所示
  
  
 采用靈敏方法進(jìn)行用戶(hù)界面開(kāi)發(fā)(圖四)
  Figure 4. The login dialog window

  
  和登錄對(duì)話框交互驗(yàn)證了用圖4所示的值登錄,會(huì)登錄成功然后窗體關(guān)閉。試著用其它的值登錄,窗體將保持打開(kāi),因?yàn)榈卿浭×恕H∠粹o關(guān)閉窗體,就象窗體的關(guān)閉按鈕一樣。這個(gè)登錄對(duì)話框就如同設(shè)計(jì)的那樣運(yùn)行。
  
  解決方案
  
  我們已經(jīng)根據(jù)TDD創(chuàng)建了登錄對(duì)話框和一個(gè)靈敏對(duì)象/瘦視圖設(shè)計(jì)模式。得到了一個(gè)有很好構(gòu)架和功能的程序。有功能的應(yīng)用行為被單元測(cè)試所覆蓋,普通的用來(lái)顯示的代碼不需要復(fù)雜的GUI測(cè)試。圖5展示了我們所開(kāi)發(fā)的這個(gè)軟件的構(gòu)架。
  
  
 采用靈敏方法進(jìn)行用戶(hù)界面開(kāi)發(fā)(圖五)
  Figure 5. The classes LoginDialog, LoginDialogView, and LoginDialogTest
  

  基于此,其他的特性可以被加入。登錄對(duì)話框可以有一個(gè)消息域去提醒用戶(hù)登錄失敗。其他的登陸參數(shù)域也可以被加入。一個(gè)單獨(dú)的驗(yàn)證對(duì)象可以被創(chuàng)建,硬編碼的登錄值可以被刪掉。不管怎么變化,TDD和靈敏對(duì)象/瘦視圖模式提供了一個(gè)設(shè)計(jì)和實(shí)現(xiàn)上的清楚的方向。重要的應(yīng)用功能是在于可以測(cè)試的靈敏的對(duì)象,和在瘦視圖中普通的顯示用的代碼的。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 屯门区| 昌吉市| 兖州市| 德惠市| 柳江县| 常宁市| 盐山县| 盐亭县| 商城县| 隆子县| 修武县| 府谷县| 新宾| 涞水县| 三河市| 玉溪市| 仁怀市| 冕宁县| 洛扎县| 陆川县| 牙克石市| 蓬溪县| 玛沁县| 红桥区| 荔浦县| 德钦县| 宁津县| 瑞丽市| 河北区| 军事| 平泉县| 客服| 馆陶县| 石阡县| 舒城县| 泾阳县| 孙吴县| 容城县| 抚宁县| 永清县| 罗城|