<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

    Android JUnit test 進(jìn)行自動(dòng)化測(cè)試

      一. 被test的工程:
      新建一個(gè)android工程:D_session;它有一個(gè)activity:D_sessionActivity;package名:com.mysession
      二.測(cè)試工程:
      新建一個(gè)測(cè)試工程:D_sessionTest, 類(lèi)型是android test project;
      1. menifest文件:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mysession.test"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="8" />
    <instrumentation
    android:name="android.test.InstrumentationTestRunner"
    android:targetPackage="com.mysession" />
    <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <uses-library android:name="android.test.runner" />
    </application>
    </manifest>
      2. 一個(gè)base activity 來(lái)定義各種模擬測(cè)試者的動(dòng)作和判斷測(cè)試結(jié)果,各個(gè)測(cè)試類(lèi)都繼承該類(lèi):
    package com.mysession.test;
    import android.app.Activity;
    import android.app.Instrumentation;
    import android.app.Instrumentation.ActivityMonitor;
    import android.content.Intent;
    import android.test.InstrumentationTestCase;
    import android.test.TouchUtils;
    import android.widget.Button;
    import android.widget.TextView;
    import com.mysession.D_sessionActivity;
    public class SessionActivityTest extends InstrumentationTestCase {
    private Instrumentation mInstrumentation;
    private ActivityMonitor mSessionMonitor;
    private Activity mCurrentActivity, mSessionActivity;
    private String TextNotEqual = "text not equal.";
    private static final String PackageName = "com.mysession";
    @Override
    protected void setUp() throws Exception {
    // 初始化
    super.setUp();
    if (mInstrumentation == null) {
    mInstrumentation = getInstrumentation();
    }
    mSessionActivity = null;
    }
    @Override
    protected void tearDown() throws Exception {
    super.tearDown();
    //釋放資源
    closeActivity(mSessionActivity);
    mCurrentActivity = null;
    }
    private void closeActivity(Activity activity) {
    if(activity != null){
    activity.finish();
    activity = null;
    }
    }
    public void openSessionActivity() {
    // 打開(kāi)session activity
    try {
    setUp();
    } catch (Exception e) {
    e.printStackTrace();
    }
    mSessionMonitor = mInstrumentation.addMonitor(
    D_sessionActivity.class.getName(), null, false);
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setClassName(PackageName, D_sessionActivity.class.getName());
    mInstrumentation.startActivitySync(intent);
    mSessionActivity = getInstrumentation().waitForMonitor(mSessionMonitor);
    assertNotNull(mSessionActivity);
    mCurrentActivity = mSessionActivity;
    }
    //判斷text是否正確
    public void assertTextEqual(int resId, String strText) {
    TextView textView = (TextView) mCurrentActivity.findViewById(resId);
    assertNotNull(textView);
    assertEquals(TextNotEqual,
    strText,
    textView.getText().toString());
    };
    // 模擬按鈕點(diǎn)擊事件
    public void clickButton(int resId){
    Button button = (Button) mCurrentActivity.findViewById(resId);
    assertNotNull(button);
    TouchUtils.clickView(this, button);
    }
    }
     3. 各個(gè)測(cè)試類(lèi):
      測(cè)試類(lèi)一:
    package com.mysession.test.cases;
    import com.mysession.R;
    import com.mysession.test.SessionActivityTest;
    public class MyCase1 extends SessionActivityTest {
    public void testCase1() {
    openSessionActivity();
    assertTextEqual(R.id.etUrl,
    "http://172.20.230.5/iportal/samples/jsapi/mobile.html");
    }
    public void testCase3() {
    openSessionActivity();
    clickButton(R.id.btnLoad);
    clickButton(R.id.btnHistory);
    }
    }
      測(cè)試類(lèi)二:
    package com.mysession.test.cases;
    import com.mysession.R;
    import com.mysession.test.SessionActivityTest;
    public class MyCase2 extends SessionActivityTest{
    public void testCase2() {
    openSessionActivity();
    clickButton(R.id.btnLoad);
    }
    }
      三. 有些動(dòng)作(如點(diǎn)擊menu)需要通過(guò)包robotium-solo-1.8.0.jar來(lái)完成。
      所以要在Build Path->Configure Build Path…中導(dǎo)入:robotium-solo-1.8.0.jar
      程序中:
      private Solo solo;
      solo = new Solo(getInstrumentation(),getActivity);
      就可以使用solo了, 如:
      solo.clickOnMenuItem(text);
      solo.goBack();

    posted @ 2014-08-13 09:52 順其自然EVO 閱讀(316) | 評(píng)論 (0)編輯 收藏

    Web自動(dòng)化測(cè)試原理

     目前有很多Web UI自動(dòng)化測(cè)試框架,如WatiN,Selinimu,WebDriver等,這些框架都可以操作Web中的控件,模擬用戶輸入,點(diǎn)擊等操作,實(shí)現(xiàn)Web自動(dòng)化測(cè)試。其實(shí)這些工具的原理都一樣,都是通過(guò)調(diào)用IE COM接口和HTMLDOM 對(duì)IE瀏覽器以及WEB測(cè)試對(duì)象的操作。 本文介紹脫離這些自動(dòng)化測(cè)試框架,通過(guò)AutoIT直接使用IE COM接口結(jié)合HTML DOM對(duì)IE瀏覽器以及WEB對(duì)象進(jìn)行自動(dòng)化測(cè)試的方法。
      1.IE常用操作
      首先新建一個(gè)IE COM對(duì)象,配置IE窗口屬性,模擬用戶同時(shí)跳轉(zhuǎn)至相應(yīng)的頁(yè)面同時(shí)進(jìn)行相應(yīng)操作。訪問(wèn)頁(yè)面時(shí),需要等待頁(yè)面加載完成后再進(jìn)行操作。這里我們可以使用IE COM的BUSY屬性檢查瀏覽器是否處于加載狀態(tài),再進(jìn)行相應(yīng)的操作。示例代碼如下:
      2.利用DOM操作測(cè)試對(duì)象
      現(xiàn)在已經(jīng)會(huì)使用IE COM組件來(lái)對(duì)IE瀏覽器進(jìn)行自動(dòng)化的操作,但是對(duì)于瀏覽器頁(yè)面中的測(cè)試對(duì)象IE COM是無(wú)法對(duì)其進(jìn)行操作的,這個(gè)時(shí)候就需要使用HTML DOM來(lái)對(duì)其進(jìn)行操作。
      2.1 HTML DOM簡(jiǎn)介
      HTML DOM是HTML Document Object Model(文檔對(duì)象模型)的縮寫(xiě),它將網(wǎng)頁(yè)中的各個(gè)元素都看作一個(gè)個(gè)對(duì)象,從而使網(wǎng)頁(yè)中的元素也可以被計(jì)算機(jī)語(yǔ)言獲取或者編輯。 常用DOM 屬性如下:
      className.同一樣式規(guī)則的元素用相同的類(lèi)名。可以通過(guò)className快速過(guò)濾出一組類(lèi)似的元素。
      document.用于指向包含當(dāng)前元素的文檔對(duì)象。
      id.當(dāng)前元素的標(biāo)識(shí)。如果文檔中包含多個(gè)相同id的元素,則返回一個(gè)數(shù)組。
      innerHTML.用于指向當(dāng)前元素的開(kāi)始標(biāo)記和結(jié)束標(biāo)記之間的所有文本和HTML標(biāo)簽。
      innerText.用于指向當(dāng)前元素的開(kāi)始標(biāo)記和結(jié)束標(biāo)記之間的所有文本和HTML標(biāo)簽。
      offsetHeight, offsetWidth.元素的高度和寬度。
      offsetLeft, offsetTop.當(dāng)前元素相同對(duì)于父親元素的左邊位置和頂部位置。
      outerHTML.當(dāng)前元素的開(kāi)始標(biāo)記和結(jié)束標(biāo)記之間的所有文本和HTML標(biāo)簽。
      outerText.當(dāng)前元素的開(kāi)始標(biāo)記和結(jié)束標(biāo)記之間的所有文本,但不包括HTML標(biāo)簽。
      parentElement.當(dāng)前元素的父親元素。
      sourceIndex.元素在document.all集合中的索引(index)。
      style.元素的樣式表單屬性。
      tagName.當(dāng)前元素的標(biāo)簽名。
      title.在IE中,代表元素的tool tip文本
      常用DOM方法如下:
      click().模擬用戶對(duì)當(dāng)前元素的鼠標(biāo)點(diǎn)擊。
      contains(element).用于判斷當(dāng)前元素是否包含指定的元素。
      getAttribute(attributeName, caseSensitive).返回當(dāng)前元素所包含的某個(gè)屬性,參數(shù)attributeName為屬性名、caseSensitive表示是否大小寫(xiě)敏感。
      setAttribute(attributeName, value, caseSenstive). 設(shè)置當(dāng)前元素的屬性。
      常用DOM 集合如下:
      All[].當(dāng)前元素中包含的所有HTML元素的數(shù)組。
      children[].當(dāng)前元素包含的子元素。
      2.2 種方法對(duì)比
      2.2.1getElementByID
      getElementByID( )方法可根據(jù)指定的id屬性值得到對(duì)象。 首先需要分析頁(yè)面,在Chome瀏覽器中選擇相應(yīng)的網(wǎng)頁(yè)元素點(diǎn)擊右鍵選擇"審查元素"(或使用IE Develop Toolbar或者firebug等插件亦可),即可得到頁(yè)面控件的ID等信息。  通過(guò)getElementByID方法獲取百度搜索框及搜索按鈕對(duì)象,并對(duì)其進(jìn)行輸入及點(diǎn)擊操作,從而完成搜索操作。示例代碼如下:
      2.2.2getElementsByName
      getElementsByName( )方法可返回帶有指定名稱(chēng)的對(duì)象的集合。
      同樣獲取網(wǎng)頁(yè)元素name后,即可通過(guò)getElementsByName方法獲取定位對(duì)象,并對(duì)其進(jìn)行操作(與getElementByID返回的單個(gè)對(duì)象不同,getElementsByName返回的是一個(gè)元素的集合,需要通過(guò)遍歷對(duì)象才能對(duì)其進(jìn)行操作):
      2.2.3getElementsByTagName
      getElementsByTagName( )方法通過(guò)查找整個(gè)HTML文檔中的任何HTML元素,傳回指定名稱(chēng)的元素集合。 因此也可使用getElementsByTagName獲取TAG名,通過(guò)得到相同類(lèi)型的元素及在遍歷中進(jìn)行判斷控件類(lèi)型并進(jìn)行操作:
      2.3 利用FORM名來(lái)獲取對(duì)象元素
      使用FORM名來(lái)獲取對(duì)象元素會(huì)大大簡(jiǎn)化我們的腳本。首先查看百度的搜索框?qū)?yīng)的FORM名,得到FORM名為f: 
    通過(guò)如下簡(jiǎn)單的腳本,同樣可以達(dá)到相同的效果:
      2.4 訪問(wèn)Web頁(yè)面的Script腳本變量
      通過(guò)DOM還可以直接訪問(wèn)Web頁(yè)面中的JavaScript或者VBScript中的變量。首先打開(kāi)百度的源文件:
      可以看到在百度源文件的JavaScript腳本中定義了一個(gè)變量為k,并且賦值為d.f.wd(實(shí)際上就是百度搜索框?qū)ο螅D敲纯梢灾苯邮褂胮arentWindow來(lái)訪問(wèn)Web頁(yè)面Script中的變量k,對(duì)百度搜索框進(jìn)行自動(dòng)測(cè)試:
      3 總結(jié)
      本文主要介紹了利用IE的COM以及HTML DOM來(lái)自動(dòng)化IE瀏覽器,以及對(duì)瀏覽器的一些控件對(duì)象進(jìn)行自動(dòng)化的操作,包括IE瀏覽器常用操作、利用DOM操作測(cè)試對(duì)象、利用FORM名來(lái)獲取對(duì)象元素、訪問(wèn)Web頁(yè)面的Script腳本變量等。 直接操作IE COM來(lái)實(shí)現(xiàn)Web自動(dòng)化,不僅有助于有助于理解Web頁(yè)面自動(dòng)化測(cè)試框架的運(yùn)行原理,還能脫離這些自動(dòng)化測(cè)試框架自己快速建立一個(gè)輕量型的自動(dòng)化測(cè)試程序,從而真正的提高測(cè)試效率。
    原文鏈接:http://lovesoo.org/web-automation-testing-principle.html

    posted @ 2014-08-13 09:49 順其自然EVO 閱讀(886) | 評(píng)論 (0)編輯 收藏

    Junit單元測(cè)試小應(yīng)用

      測(cè)試是一個(gè)很重要的問(wèn)題,我覺(jué)得:一個(gè)程序員行不行,關(guān)鍵看他會(huì)不會(huì)調(diào)試。程序的測(cè)試都是從小范圍入手然后向四面八方入手,一點(diǎn)點(diǎn)的向外擴(kuò)展,直至最后程序整體運(yùn)行良好。這只是在下的一點(diǎn)愚見(jiàn)。以前進(jìn)行調(diào)試時(shí)總是在程序中寫(xiě)個(gè)main方法,然后進(jìn)行測(cè)試,以前學(xué)過(guò)一個(gè)Junit單元測(cè)試,沒(méi)想起來(lái)用,今天看見(jiàn)老師的代碼中有這個(gè)單元測(cè)試,所以下來(lái)了看了看以前的代碼并上網(wǎng)查了查有關(guān)Junit的東西,在此簡(jiǎn)單的說(shuō)一下。以MyElipse 8.5 進(jìn)行說(shuō)明。
      1.新建一個(gè)project,然后右擊選擇properties-----Java Build Path-----Libraries---AddLibrary---Junit,將Junit插件添加到該項(xiàng)目中。
      2.在project中建立一個(gè)JDemo.java 和 Test.java,JDemo中由一個(gè)簡(jiǎn)單的方法add(),Test要繼承TestCase,代碼如下:
    JDemo.java
    package com.bx.testjunit;
    public class JDemo {
    int a;
    int b;
    int result;
    public int add(int a,int b){
    result = a + b;
    return result;
    }
    }
    Test.java
    package com.bx.testjunit;
    import junit.framework.TestCase;
    import org.junit.After;
    import org.junit.Before;
    public class Test extends TestCase{
    @Before
    public void setUp() throws Exception {
    System.out.println("Test :setUp");
    }
    @After
    public void tearDown() throws Exception {
    System.out.println("Test :tearDown");
    }
    public void test(){
    JDemo a = new JDemo();
    assertEquals(6,a.add(3, 3));
    }
    }
      3.運(yùn)行,右擊Junit Test,在控制臺(tái)上會(huì)出來(lái)一個(gè)Junit選項(xiàng)卡,如果出現(xiàn)綠顏色的bar則說(shuō)明程序正確,如果是紅顏色的bar則說(shuō)明程序錯(cuò)誤,需進(jìn)行檢錯(cuò)。
      上面的程序用的是Junit3,必須繼承TestCase
      下面看一個(gè)Junit4的例子
    package com.bx.service;
    import org.junit.Test;
    public class HelloWorld {
    @Test
    public void test(){
    System.out.println("HelloWord :test");
    }
    }
      Junit4不需要繼承TestCase,只需使用@Test標(biāo)注的expected屬性。

    posted @ 2014-08-13 09:47 順其自然EVO 閱讀(201) | 評(píng)論 (0)編輯 收藏

    如何寫(xiě)功能測(cè)試報(bào)告

    1、項(xiàng)目進(jìn)度
      1.1測(cè)試執(zhí)行階段
      寫(xiě)清楚當(dāng)前是在冒煙測(cè)試功能測(cè)試執(zhí)行階段,還是回歸測(cè)試階段
      寫(xiě)清楚當(dāng)前階段預(yù)計(jì)在什么時(shí)候結(jié)束(在可控的情況下,如果不可控或者不可預(yù)測(cè),說(shuō)明風(fēng)險(xiǎn)在哪里)
      寫(xiě)清楚當(dāng)前測(cè)試了哪個(gè)模塊,還有哪些模塊沒(méi)有測(cè)試(一般都是先測(cè)試優(yōu)先級(jí)高的模塊)
      寫(xiě)清楚下個(gè)星期的測(cè)試計(jì)劃是什么
      2、測(cè)試情況
      2.1 再介紹一下本周的測(cè)試模塊
      2.2 寫(xiě)清楚當(dāng)前模塊的質(zhì)量情況:open了多少bug,fix了多少,close了多少。bug的趨勢(shì)是什么(后期應(yīng)當(dāng)收斂,在前期如果未收斂,解釋未收斂的原因)
      2.3 本周遇到的問(wèn)題是什么(風(fēng)險(xiǎn)是什么)
      3、貼圖
      3.1 相關(guān)圖片,有需要解釋的進(jìn)行解釋?zhuān)ㄈ鐁eopen的bug,高級(jí)別的bug)

    posted @ 2014-08-13 09:46 順其自然EVO 閱讀(250) | 評(píng)論 (0)編輯 收藏

    Java 接口和抽象類(lèi)區(qū)別

    1.概述

    一個(gè)軟件設(shè)計(jì)的好壞,我想很大程度上取決于它的整體架構(gòu),而這個(gè)整體架構(gòu)其實(shí)就是你對(duì)整個(gè)宏觀商業(yè)業(yè)務(wù)的抽象框架,當(dāng)代表業(yè)務(wù)邏輯的高層抽象層結(jié)構(gòu) 合理時(shí),你底層的具體實(shí)現(xiàn)需要考慮的就僅僅是一些算法和一些具體的業(yè)務(wù)實(shí)現(xiàn)了。當(dāng)你需要再開(kāi)發(fā)另一個(gè)相近的項(xiàng)目時(shí),你以前的抽象層說(shuō)不定還可以再次利用 。面對(duì)對(duì)象的設(shè)計(jì),復(fù)用的重點(diǎn)其實(shí)應(yīng)該是抽象層的復(fù)用,而不是具體某一個(gè)代碼塊的復(fù)用

    說(shuō)到了抽象,我就不能不提到曾讓我頭痛的Java接口和Java抽象類(lèi)了,這也是本文我想說(shuō)的重點(diǎn)。

    既然面向?qū)ο笤O(shè)計(jì)的重點(diǎn)在于抽象,那Java接口和Java抽象類(lèi)就有它存在的必然性了。

    Java接口(interface)和Java抽象類(lèi)(abstract class)代表的就是抽象類(lèi)型,就是我們需要提出的抽象層的具體表現(xiàn)。OOP面向?qū)ο蟮木幊蹋绻岣叱绦虻膹?fù)用率,增加程序 的可維護(hù)性,可擴(kuò)展性,就必須是面向接口的編程,面向抽象的編程,正確地使用接口、抽象類(lèi)這些有用的抽象類(lèi)型作為你結(jié)構(gòu)層次上的頂層。

    Java接口和Java抽象類(lèi)有太多相似的地方,又有太多特別的地方,究竟在什么地方,才是它們的最佳位置呢?把它們比較一下,你就可以發(fā)現(xiàn)了。

    1. Java接口和Java抽象類(lèi)最大的一個(gè)區(qū)別,就在于Java抽象類(lèi)可以提供某些方法的部分實(shí)現(xiàn),而Java接口不可以(就是interface中只能定義方法,而不能有方法的實(shí)現(xiàn),而在abstract class中則可以既有方法的具體實(shí)現(xiàn),又有沒(méi)有具體實(shí)現(xiàn)的抽象方法),這大概就是Java抽象類(lèi)唯一的優(yōu)點(diǎn)吧,但這個(gè)優(yōu)點(diǎn)非常有用。如果向一個(gè)抽象類(lèi)里加入一個(gè)新的具體方法時(shí),那么它所有的子類(lèi)都一下子都得到了這個(gè)新方法,而Java接口做不到這一點(diǎn),如果向一個(gè)Java接口里加入一個(gè) 新方法,所有實(shí)現(xiàn)這個(gè)接口的類(lèi)就無(wú)法成功通過(guò)編譯了,因?yàn)槟惚仨氉屆恳粋€(gè)類(lèi)都再實(shí)現(xiàn)這個(gè)方法才行,這顯然是Java接口的缺點(diǎn)這個(gè)在我的另外一篇博客mapreduce 新舊API 區(qū)別中有提到類(lèi)似的問(wèn)題,在新的mapreduce api中更傾向于使用抽象類(lèi),而不是接口,因?yàn)檫@更容易擴(kuò)展。原因就是上面劃線部分所說(shuō)的。
    2. 一個(gè)抽象類(lèi)的實(shí)現(xiàn)只能由這個(gè)抽象類(lèi)的子類(lèi)給出,也就是說(shuō),這個(gè)實(shí)現(xiàn)處在抽象類(lèi)所定義出的繼承的等級(jí)結(jié)構(gòu)中,而由于Java語(yǔ)言的單繼承性,所以抽象類(lèi)作為類(lèi)型定義工具的效能大打折扣。在這一點(diǎn)上,Java接口的優(yōu)勢(shì)就出來(lái)了,任何一個(gè)實(shí)現(xiàn)了一個(gè)Java接口所規(guī)定的方法的類(lèi)都可以具有這個(gè)接口的類(lèi)型,而一個(gè)類(lèi)可以實(shí)現(xiàn)任意多個(gè)Java接口,從而這個(gè)類(lèi)就有了多種類(lèi)型。(使用抽象類(lèi),那么繼承這個(gè)抽象類(lèi)的子類(lèi)類(lèi)型就比較單一,因?yàn)樽宇?lèi)只能單繼承抽象類(lèi);而子類(lèi)能夠同時(shí)實(shí)現(xiàn)多個(gè)接口,因?yàn)轭?lèi)型就比較多。接口和抽象類(lèi)都可以定義對(duì)象,但是只能用他們的具體實(shí)現(xiàn)類(lèi)來(lái)進(jìn)行實(shí)例化。)
    3. 從第2點(diǎn)不難看出,Java接口是定義混合類(lèi)型的理想工具,混合類(lèi)表明一個(gè)類(lèi)不僅僅具有某個(gè)主類(lèi)型的行為,而且具有其他的次要行為。
    4. 結(jié)合1、2點(diǎn)中抽象類(lèi)和Java接口的各自優(yōu)勢(shì),具精典的設(shè)計(jì)模式就出來(lái)了:聲明類(lèi)型的工作仍然由Java接口承擔(dān),但是同時(shí)給出一個(gè)Java 抽象類(lèi),且實(shí)現(xiàn)了這個(gè)接口,而其他同屬于這個(gè)抽象類(lèi)型的具體類(lèi)可以選擇實(shí)現(xiàn)這個(gè)Java接口,也可以選擇繼承這個(gè)抽象類(lèi),也就是說(shuō)在層次結(jié)構(gòu)中,Java 接口在最上面,然后緊跟著抽象類(lèi),這下兩個(gè)的最大優(yōu)點(diǎn)都能發(fā)揮到極至了。這個(gè)模式就是“缺省適配模式”。在Java語(yǔ)言API中用了這種模式,而且全都遵循一定的命名規(guī)范:Abstract +接口名。(A extends AbstractB implements interfaceC,那么A即可以選擇實(shí)現(xiàn)(@Override)接口interfaceC中的方法,也可以選擇不實(shí)現(xiàn);A即可以選擇實(shí)現(xiàn)(@Override)抽象類(lèi)AbstractB中的方法,也可以選擇不實(shí)現(xiàn))

    Java接口和Java抽象類(lèi)的存在就是為了用于具體類(lèi)的實(shí)現(xiàn)和繼承的,如果你準(zhǔn)備寫(xiě)一個(gè)具體類(lèi)去繼承另一個(gè)具體類(lèi)的話,那你的設(shè)計(jì)就有很大問(wèn)題了。Java抽象類(lèi)就是為了繼承而存在的,它的抽象方法就是為了強(qiáng)制子類(lèi)必須去實(shí)現(xiàn)的。

    使用Java接口和抽象Java類(lèi)進(jìn)行變量的類(lèi)型聲明、參數(shù)是類(lèi)型聲明、方法的返還類(lèi)型說(shuō)明,以及數(shù)據(jù)類(lèi)型的轉(zhuǎn)換等。而不要用具體Java類(lèi)進(jìn)行變量的類(lèi)型聲明、參數(shù)是類(lèi)型聲明、方法的返還類(lèi)型說(shuō)明,以及數(shù)據(jù)類(lèi)型的轉(zhuǎn)換等。

    2.實(shí)例

    下面給出一個(gè)具體的接口Action,代碼如下所示:

    1. package org.springframework.webflow.execution;  
    2. public interface Action {  
    3.     public Event execute(RequestContext context) throws Exception;  
    4. }  
    在這個(gè)接口中,定義了一個(gè)沒(méi)有具體實(shí)現(xiàn)的方法,方法名叫做execute(),返回類(lèi)型是Event。如前面第一條所述,接口中的方法都是沒(méi)有實(shí)現(xiàn)的。這些方法的具體實(shí)現(xiàn)是在實(shí)現(xiàn)(implements)這個(gè)接口的類(lèi)中給出的。

    再來(lái)看一個(gè)實(shí)現(xiàn)Action接口的抽象類(lèi)AbstractAction,代碼如下。

    1. package org.springframework.webflow.action;  
    2.   
    3. import org.apache.commons.logging.Log;  
    4. import org.apache.commons.logging.LogFactory;  
    5. import org.springframework.beans.factory.BeanInitializationException;  
    6. import org.springframework.beans.factory.InitializingBean;  
    7. import org.springframework.util.ClassUtils;  
    8. import org.springframework.webflow.core.collection.AttributeMap;  
    9. import org.springframework.webflow.execution.Action;  
    10. import org.springframework.webflow.execution.Event;  
    11. import org.springframework.webflow.execution.RequestContext;  
    12.   
    13. public abstract class AbstractAction implements Action, InitializingBean {  
    14.   
    15.     protected final Log logger = LogFactory.getLog(getClass());  
    16.   
    17.     public EventFactorySupport getEventFactorySupport() {  
    18.         return new EventFactorySupport();  
    19.     }  
    20.   
    21.     public void afterPropertiesSet() throws Exception {  
    22.         try {  
    23.             initAction();  
    24.         } catch (Exception ex) {  
    25.             throw new BeanInitializationException("Initialization of this Action failed: " + ex.getMessage(), ex);  
    26.         }  
    27.     }  
    28.   
    29.     protected void initAction() throws Exception {  
    30.     }  
    31.   
    32.     protected Event success() {  
    33.         return getEventFactorySupport().success(this);  
    34.     }  
    35.   
    36.     protected Event success(Object result) {  
    37.         return getEventFactorySupport().success(this, result);  
    38.     }  
    39.   
    40.     protected Event error() {  
    41.         return getEventFactorySupport().error(this);  
    42.     }  
    43.   
    44.     protected Event error(Exception e) {  
    45.         return getEventFactorySupport().error(this, e);  
    46.     }  
    47.   
    48.     protected Event yes() {  
    49.         return getEventFactorySupport().yes(this);  
    50.     }  
    51.   
    52.     protected Event no() {  
    53.         return getEventFactorySupport().no(this);  
    54.     }  
    55.   
    56.     protected Event result(boolean booleanResult) {  
    57.         return getEventFactorySupport().event(this, booleanResult);  
    58.     }  
    59.   
    60.     protected Event result(String eventId) {  
    61.         return getEventFactorySupport().event(this, eventId);  
    62.     }  
    63.   
    64.     protected Event result(String eventId, AttributeMap resultAttributes) {  
    65.         return getEventFactorySupport().event(this, eventId, resultAttributes);  
    66.     }  
    67.   
    68.     protected Event result(String eventId, String resultAttributeName, Object resultAttributeValue) {  
    69.         return getEventFactorySupport().event(this, eventId, resultAttributeName, resultAttributeValue);  
    70.     }  
    71.   
    72.     public final Event execute(RequestContext context) throws Exception {  
    73.         Event result = doPreExecute(context);  
    74.         if (result == null) {  
    75.             result = doExecute(context);  
    76.             doPostExecute(context);  
    77.         } else {  
    78.             if (logger.isInfoEnabled()) {  
    79.                 logger.info("Action execution disallowed; pre-execution result is '" + result.getId() + "'");  
    80.             }  
    81.         }  
    82.         return result;  
    83.     }  
    84.   
    85.     protected String getActionNameForLogging() {  
    86.         return ClassUtils.getShortName(getClass());  
    87.     }  
    88.   
    89.     protected Event doPreExecute(RequestContext context) throws Exception {  
    90.         return null;  
    91.     }  
    92.   
    93.     //抽象方法  
    94.     protected abstract Event doExecute(RequestContext context) throws Exception;  
    95.   
    96.     protected void doPostExecute(RequestContext context) throws Exception {  
    97.     }  
    98. }  
    在抽象類(lèi)AbstractAction中,既有具體實(shí)現(xiàn)的方法,又有沒(méi)有具體實(shí)現(xiàn)的抽象方法

    1. //抽象方法  
    2. protected abstract Event doExecute(RequestContext context) throws Exception;  
    需要注意的是在抽象類(lèi)中,如果方法沒(méi)有具體實(shí)現(xiàn)(就是方法后面沒(méi)有{}),那么必須加上abstract來(lái)聲明這個(gè)方法,而接口中不需要使用abstract來(lái)聲明(抽象類(lèi)之所以被稱(chēng)為抽象類(lèi),就是因?yàn)樗谐橄蠓椒ā:谐橄蠓椒ǖ念?lèi)叫做抽象類(lèi))

    posted @ 2014-08-12 09:48 順其自然EVO 閱讀(235) | 評(píng)論 (0)編輯 收藏

    數(shù)據(jù)庫(kù)鎖和數(shù)據(jù)庫(kù)隔離級(jí)別

    最近突然發(fā)現(xiàn)忘了數(shù)據(jù)庫(kù)鎖和數(shù)據(jù)庫(kù)隔離級(jí)別,時(shí)常弄混它們之間的關(guān)系。為此特此寫(xiě)下此博客,以方便自己復(fù)習(xí),同時(shí)也可以幫助博友。
      數(shù)據(jù)庫(kù)鎖
      數(shù)據(jù)庫(kù)鎖就是事務(wù)T在對(duì)某個(gè)數(shù)據(jù)對(duì)象(例如表、記錄等)操作之前,先向系統(tǒng)發(fā)出請(qǐng)求,對(duì)其加鎖。加鎖后事務(wù)T就對(duì)該數(shù)據(jù)對(duì)象有了一定的控制,在事務(wù)T釋放它的鎖之前,其它的事務(wù)不能更新此數(shù)據(jù)對(duì)象。
      數(shù)據(jù)庫(kù)鎖是實(shí)現(xiàn)并發(fā)控制的重要技術(shù),但是“鎖”會(huì)帶來(lái)系統(tǒng)額外的開(kāi)銷(xiāo)。所以需要注意選擇封鎖粒度時(shí)必須同時(shí)考慮開(kāi)銷(xiāo)和并發(fā)度兩個(gè)因素,進(jìn)行權(quán)衡,以求得最優(yōu)的效果。
      鎖的類(lèi)型主要有兩種類(lèi)型排它鎖(也叫獨(dú)占鎖)和共享鎖,當(dāng)然還有很多教程增加了一種--更新鎖。
      共享(S)鎖:多個(gè)事務(wù)可封鎖一個(gè)共享頁(yè);任何事務(wù)都不能修改該頁(yè); 通常是該頁(yè)被讀取完畢,S鎖立即被釋放。在執(zhí)行select語(yǔ)句的時(shí)候需要給操作對(duì)象(表或者一些記錄)加上共享鎖,但加鎖之前需要檢查是否有排他鎖,如果沒(méi)有,則可以加共享鎖(一個(gè)對(duì)象上可以加n個(gè)共享鎖),否則不行。共享鎖通常在執(zhí)行完select語(yǔ)句之后被釋放,當(dāng)然也有可能是在事務(wù)結(jié)束(包括正常結(jié)束和異常結(jié)束)的時(shí)候被釋放,主要取決與數(shù)據(jù)庫(kù)所設(shè)置的事務(wù)隔離級(jí)別。
      排它(X)鎖:僅允許一個(gè)事務(wù)封鎖此頁(yè);其他任何事務(wù)必須等到X鎖被釋放才能對(duì)該頁(yè)進(jìn)行訪問(wèn);X鎖一直到事務(wù)結(jié)束才能被釋放。執(zhí)行insert、update、delete語(yǔ)句的時(shí)候需要給操作的對(duì)象加排他鎖(我感覺(jué)在執(zhí)行insert的時(shí)候應(yīng)該是在表級(jí)加排他鎖),在加排他鎖之前必須確認(rèn)該對(duì)象上沒(méi)有其他任何鎖,一旦加上排他鎖之后,就不能再給這個(gè)對(duì)象加其他任何鎖。排他鎖的釋放通常是在事務(wù)結(jié)束的時(shí)候(當(dāng)然也有例外,就是在數(shù)據(jù)庫(kù)事務(wù)隔離級(jí)別被設(shè)置成Read Uncommitted(讀未提交數(shù)據(jù))的時(shí)候,這種情況下排他鎖會(huì)在執(zhí)行完更新操作之后就釋放,而不是在事務(wù)結(jié)束的時(shí)候)。
      更新(U)鎖:用來(lái)預(yù)定要對(duì)此頁(yè)施加X(jué)鎖,它允許其他事務(wù)讀,但不允許再施加U鎖或X鎖;當(dāng)被讀取的頁(yè)將要被更新時(shí),則升級(jí)為X鎖;U鎖一直到事務(wù)結(jié)束時(shí)才能被釋放。數(shù)據(jù)庫(kù)是支持在一個(gè)事務(wù)中進(jìn)行自動(dòng)鎖升級(jí)的,例如,在某個(gè)事務(wù)中先執(zhí)行select語(yǔ)句,后執(zhí)行update語(yǔ)句,這兩條語(yǔ)句操作了同一個(gè)對(duì)象,并且假定共享鎖是在事務(wù)結(jié)束的時(shí)候被釋放的。如果數(shù)據(jù)庫(kù)不支持自動(dòng)鎖升級(jí),那么當(dāng)update語(yǔ)句請(qǐng)求排他鎖的時(shí)候?qū)⒉荒艹晒ΑR驗(yàn)橹皊elect語(yǔ)句的共享鎖沒(méi)有被釋放,那么事務(wù)就進(jìn)入了無(wú)限等待,即死鎖。有了自動(dòng)鎖升級(jí),在執(zhí)行update語(yǔ)句的時(shí)候就可以將之前加的共享鎖升級(jí)為排他鎖,但有個(gè)前提,就是這個(gè)共享鎖必須是本事務(wù)自己加的,而且在操作對(duì)象上沒(méi)有在加其他任何鎖,否則共享鎖是不能被升級(jí)為排他鎖的,必須等待其他鎖的釋放。
      因?yàn)橥ǔT趫?zhí)行更新操作的時(shí)候要先查詢,也就是我們通常會(huì)在update語(yǔ)句和delete語(yǔ)句中加where子句。那么,有的數(shù)據(jù)庫(kù)系統(tǒng)可能會(huì)在執(zhí)行查詢的時(shí)候先給操作對(duì)象加共享鎖,然后在更新的時(shí)候加排他鎖,但這么做會(huì)有問(wèn)題,也就是如果兩個(gè)事務(wù)同時(shí)要更新一個(gè)對(duì)象,都先給這個(gè)對(duì)象加了共享鎖,當(dāng)要更新的時(shí)候,都請(qǐng)求升級(jí)鎖,但由于這個(gè)對(duì)象上存在對(duì)方事務(wù)加的共享鎖。。所以無(wú)法升級(jí)。這樣兩個(gè)事務(wù)就在等待對(duì)方釋放共享鎖,進(jìn)入死鎖狀態(tài)。更新鎖就是為了解決這個(gè)問(wèn)題,即在執(zhí)行查詢操作的時(shí)候加的不是共享鎖而是更新鎖(一個(gè)對(duì)象上只能有一個(gè)更新鎖和n個(gè)共享鎖),當(dāng)要更新的時(shí)候,再將更新鎖升級(jí)為排他鎖,升級(jí)前提是這個(gè)對(duì)象上只有本事務(wù)加的更新鎖,沒(méi)有其他任何鎖了。其實(shí),,我想,如果在執(zhí)行查詢的時(shí)候就給事務(wù)加排他鎖不也能解決死鎖問(wèn)題嗎,但這樣似乎會(huì)減弱系統(tǒng)的并發(fā)性能。
      數(shù)據(jù)庫(kù)的事務(wù)隔離級(jí)別
      在數(shù)據(jù)庫(kù)操作中,為了有效保證并發(fā)讀取數(shù)據(jù)的正確性,提出的事務(wù)隔離級(jí)別。
    在沒(méi)有數(shù)據(jù)庫(kù)的事務(wù)隔離級(jí)別時(shí)會(huì)出現(xiàn)如下問(wèn)題:
      更新丟失
      兩個(gè)事務(wù)都同時(shí)更新一行數(shù)據(jù),但是第二個(gè)事務(wù)卻中途失敗退出,導(dǎo)致對(duì)數(shù)據(jù)的兩個(gè)修改都失效了。這是因?yàn)橄到y(tǒng)沒(méi)有執(zhí)行任何的鎖操作,因此并發(fā)事務(wù)并沒(méi)有被隔離開(kāi)來(lái)。
      臟讀
      一個(gè)事務(wù)開(kāi)始讀取了某行數(shù)據(jù),但是另外一個(gè)事務(wù)已經(jīng)更新了此數(shù)據(jù)但沒(méi)有能夠及時(shí)提交。這是相當(dāng)危險(xiǎn)的,因?yàn)楹芸赡芩械牟僮鞫急换貪L。
      不可重復(fù)讀
      不可重復(fù)讀(Non-repeatable Reads):一個(gè)事務(wù)對(duì)同一行數(shù)據(jù)重復(fù)讀取兩次,但是卻得到了不同的結(jié)果。
      包括以下情況:
      (1) 事務(wù)T1讀取某一數(shù)據(jù)后,事務(wù)T2對(duì)其做了修改,當(dāng)事務(wù)T1再次讀該數(shù)據(jù)時(shí)得到與前一次不同的值。
      (2) 幻讀(Phantom Reads):事務(wù)在操作過(guò)程中進(jìn)行兩次查詢,第二次查詢的結(jié)果包含了第一次查詢中未出現(xiàn)的數(shù)據(jù)或者缺少了第一次查詢中出現(xiàn)的數(shù)據(jù)(這里并不要求兩次查詢的SQL語(yǔ)句相同)。這是因?yàn)樵趦纱尾樵冞^(guò)程中有另外一個(gè)事務(wù)插入數(shù)據(jù)造成的。
      為了避免上面出現(xiàn)的幾種情況,在標(biāo)準(zhǔn)SQL規(guī)范中,定義了4個(gè)事務(wù)隔離級(jí)別,不同的隔離級(jí)別對(duì)事務(wù)的處理不同。
      未授權(quán)讀取
      也稱(chēng)為讀未提交(Read Uncommitted):允許臟讀取,但不允許更新丟失。如果一個(gè)事務(wù)已經(jīng)開(kāi)始寫(xiě)數(shù)據(jù),則另外一個(gè)事務(wù)則不允許同時(shí)進(jìn)行寫(xiě)操作,但允許其他事務(wù)讀此行數(shù)據(jù)。該隔離級(jí)別可以通過(guò)“排他寫(xiě)鎖”實(shí)現(xiàn)。
      授權(quán)讀取
      也稱(chēng)為讀提交(Read Committed):允許不可重復(fù)讀取,但不允許臟讀取。這可以通過(guò)“瞬間共享讀鎖”和“排他寫(xiě)鎖”實(shí)現(xiàn)。讀取數(shù)據(jù)的事務(wù)允許其他事務(wù)繼續(xù)訪問(wèn)該行數(shù)據(jù),但是未提交的寫(xiě)事務(wù)將會(huì)禁止其他事務(wù)訪問(wèn)該行。
      可重復(fù)讀取(Repeatable Read)
      可重復(fù)讀取(Repeatable Read):禁止不可重復(fù)讀取和臟讀取,但是有時(shí)可能出現(xiàn)幻影數(shù)據(jù)。這可以通過(guò)“共享讀鎖”和“排他寫(xiě)鎖”實(shí)現(xiàn)。讀取數(shù)據(jù)的事務(wù)將會(huì)禁止寫(xiě)事務(wù)(但允許讀事務(wù)),寫(xiě)事務(wù)則禁止任何其他事務(wù)。
      序列化(Serializable)
      序列化(Serializable):提供嚴(yán)格的事務(wù)隔離。它要求事務(wù)序列化執(zhí)行,事務(wù)只能一個(gè)接著一個(gè)地執(zhí)行,但不能并發(fā)執(zhí)行。如果僅僅通過(guò)“行級(jí)鎖”是無(wú)法實(shí)現(xiàn)事務(wù)序列化的,必須通過(guò)其他機(jī)制保證新插入的數(shù)據(jù)不會(huì)被剛執(zhí)行查詢操作的事務(wù)訪問(wèn)到。
      隔離級(jí)別越高,越能保證數(shù)據(jù)的完整性和一致性,但是對(duì)并發(fā)性能的影響也越大。對(duì)于多數(shù)應(yīng)用程序,可以優(yōu)先考慮把數(shù)據(jù)庫(kù)系統(tǒng)的隔離級(jí)別設(shè)為Read Committed。它能夠避免臟讀取,而且具有較好的并發(fā)性能。盡管它會(huì)導(dǎo)致不可重復(fù)讀、虛讀和第二類(lèi)丟失更新這些并發(fā)問(wèn)題,在可能出現(xiàn)這類(lèi)問(wèn)題的個(gè)別場(chǎng)合,可以由應(yīng)用程序采用悲觀鎖或樂(lè)觀鎖來(lái)控制。

    posted @ 2014-08-12 09:36 順其自然EVO 閱讀(223) | 評(píng)論 (0)編輯 收藏

    iOS-三步快速集成社交化分享工具ShareSDK

     1.前言
      作為現(xiàn)在App里必不可少的用戶分享需要,社交化分享顯然是我們開(kāi)發(fā)app里較為常用的。
      最近因?yàn)楣続pp有社交化分享的需要,就特此研究了會(huì),拿出來(lái)與大家分享。
      想要集成社交會(huì)分享,我們可以使用
      ShareSDK - 優(yōu)點(diǎn)功能豐富,缺點(diǎn)體積較大
      百度分享SDK - 缺點(diǎn)功能相對(duì)ShareSDK較少,優(yōu)點(diǎn)體積較小
      這是現(xiàn)在較為常用的兩種社交化分享工具。
      使用哪一種,就看個(gè)人的app的需要來(lái)決定了。
      今天我主要說(shuō)的是ShareSDK的簡(jiǎn)單集成和使用。
      2.集成前的準(zhǔn)備工作
      2.1. 拿自己的Appkey 去下載ShareSDK
      下載地址:http://sharesdk.cn/Download
      2.2. 申請(qǐng)分享工具的Appkey
      例如: 新浪微博、騰訊微博、豆瓣應(yīng)用、人人網(wǎng)、QQ空間
      去各大社交網(wǎng)站的開(kāi)發(fā)者平臺(tái),進(jìn)行注冊(cè)申請(qǐng)即可。
      獲取如下:
      //新浪微博:
      //App Key:2258477553
      //App Secret:1e2f275afc375109e456f550fb3918e8
      //騰訊微博:
      //App key:2620460989
      //App secret:58c55f572d5ae35e0c355f4c0ee11283
      3.集成ShareSDK
      3.1.注冊(cè)使用ShareSDK
      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
      {
      //注冊(cè)ShareSDK
      [ShareSDK registerApp:@"1983bf0916db”];
      return YES;
      }
      3.2.添加要集成的分享平臺(tái)
      注意: 新浪微博需要提供回調(diào)地址才行
      回調(diào)地址去新浪開(kāi)發(fā)者平臺(tái)獲取
      如圖:
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    //注冊(cè)ShareSDK
    [ShareSDK registerApp:@"1983bf0916db”];
    //添加新浪微博應(yīng)用
    [ShareSDK connectSinaWeiboWithAppKey:@"2620460989"
    appSecret:@"58c55f572d5ae35e0c355f4c0ee11283"
    redirectUri:@"http://weibo.cn/ext/share?ru=http%3A%2F%2F16kxs.com%2Fwap%2FBook%2FShow.aspx%3Fid%3D7983%26lmid%3D0%26uid%3D0%26ups%3D0&rt=%E9%83%BD%E5%B8%82%E7%89%A7%E9%AC%BC%E4%BA%BA&st=1301645308&appkey=2620460989”];
    //添加騰訊微博應(yīng)用
    [ShareSDK connectTencentWeiboWithAppKey:@"801307650"
    appSecret:@"ae36f4ee3946e1cbb98d6965b0b2ff5c"
    redirectUri:@"http://www.sharesdk.cn"];
    //添加豆瓣應(yīng)用
    [ShareSDK connectDoubanWithAppKey:@"07d08fbfc1210e931771af3f43632bb9"
    appSecret:@"e32896161e72be91"
    redirectUri:@"http://dev.kumoway.com/braininference/infos.php"];
    //添加人人網(wǎng)應(yīng)用
    [ShareSDK connectRenRenWithAppKey:@"fc5b8aed373c4c27a05b712acba0f8c3"
    appSecret:@"f29df781abdd4f49beca5a2194676ca4"];
    //添加Facebook應(yīng)用
    [ShareSDK connectFacebookWithAppKey:@"107704292745179"
    appSecret:@"38053202e1a5fe26c80c753071f0b573"];
    }
      3.3.彈出分享View
      a.初始化默認(rèn)分享內(nèi)容
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"123"  ofType:@"png"];
    //構(gòu)建優(yōu)秀的SDK
    //構(gòu)造分享內(nèi)容
    id<ISSContent> publishContent = [ShareSDK content:@"iOS社交化分享測(cè)試內(nèi)容。"
    defaultContent:@"默認(rèn)分享內(nèi)容,沒(méi)內(nèi)容時(shí)顯示"
    image:[ShareSDK imageWithPath:imagePath]
    title:@"ShareSDK"
    url:@"http://www.sharesdk.cn"
    description:@"這是一條測(cè)試信息"
    mediaType:SSPublishContentMediaTypeNews];
      b.彈出分享View
    [ShareSDK showShareActionSheet:nil
    shareList:nil
    content:publishContent
    statusBarTips:YES
    authOptions:nil
    shareOptions: nil
    result:^(ShareType type, SSResponseState state, id<ISSPlatformShareInfo> statusInfo, id<ICMErrorInfo> error, BOOL end) {
    if (state == SSResponseStateSuccess)
    {
    NSLog(@"分享成功");
    }
    else if (state == SSResponseStateFail)
    {
    NSLog(@"分享失敗,錯(cuò)誤碼:%d,錯(cuò)誤描述:%@", [error errorCode], [error errorDescription]);
    }
    }];
      效果圖:

    posted @ 2014-08-12 09:36 順其自然EVO 閱讀(1346) | 評(píng)論 (0)編輯 收藏

    Java變量初始化的時(shí)機(jī)

      對(duì)于JAVA中變量的初始化是一個(gè)很基礎(chǔ)的問(wèn)題,其中的一些問(wèn)題也是易被學(xué)習(xí)者所忽略。當(dāng)在編寫(xiě)代碼的時(shí)候碰到時(shí),常被這些問(wèn)題引發(fā)的錯(cuò)誤,感覺(jué)莫名其妙。而且現(xiàn)在許多大公司的面試題,對(duì)于這方面的考查也是屢試不爽。以下是對(duì)java變量初始化的時(shí)機(jī)的分析。
      【java變量執(zhí)行初始化的步驟】
      java是一門(mén)強(qiáng)類(lèi)型語(yǔ)言,因此java語(yǔ)言規(guī)定每個(gè)變量必須先聲明,然后才能使用,聲明變量時(shí)必須指定該變量的數(shù)據(jù)類(lèi)型。首先看下面這條語(yǔ)句的執(zhí)行過(guò)程:
      int a = 5;
      實(shí)際上面這條語(yǔ)句會(huì)被拆分成兩個(gè)過(guò)程執(zhí)行:
      (1)int a ;//創(chuàng)建java對(duì)象時(shí)根據(jù)該語(yǔ)句為變量分配內(nèi)存空間;
      (2)a = 5;//賦值操作會(huì)最終被提取到構(gòu)造器中執(zhí)行初始化操作。
      實(shí)際上在java中,在使用new操作符創(chuàng)建一個(gè)類(lèi)的實(shí)例對(duì)象的時(shí)候,開(kāi)始分配空間并將成員變量初始化為默認(rèn)的數(shù)值,在這里并不是指將變量初始化為在變量定義處的初始值,對(duì)于基本類(lèi)型變量,默認(rèn)值空值是0或false,對(duì)于引用類(lèi)型變量,默認(rèn)空值為null。這一切都是在構(gòu)造函數(shù)執(zhí)行之前,變量的真正初始化是在構(gòu)造函數(shù)中執(zhí)行。
      【java中變量初始化的時(shí)機(jī)】
      1、程序可以在3個(gè)地方對(duì)實(shí)例變量進(jìn)行初始化:
      (1)定義實(shí)例變量的時(shí)候指定初始值;
      (2)非靜態(tài)初始化代碼塊中對(duì)實(shí)例變量指定初值;
      (3)構(gòu)造器中對(duì)實(shí)例變量指定初值。
      雖然程序在3個(gè)地方都可對(duì)實(shí)例變量指定初始值,但(1)、(2)處的賦值操作最終會(huì)被提取到構(gòu)造器中執(zhí)行。且(1)、(2)的執(zhí)行順序與他們?cè)谠闯绦蛑谐霈F(xiàn)的順序相同。可以通過(guò)JDK的javap工具來(lái)看程序的執(zhí)行過(guò)程:
      2、java中類(lèi)變量初始化的時(shí)機(jī):
      (1)定義類(lèi)變量的時(shí)候指定初始值;
      (2)靜態(tài)初始化代碼塊中對(duì)類(lèi)變量指定初值。
      這里類(lèi)變量初始化的時(shí)機(jī)為兩處,而沒(méi)有在構(gòu)造器中這一說(shuō)。這也很容易理解,因?yàn)轭?lèi)變量是類(lèi)加載的時(shí)候執(zhí)行的初始化,且只執(zhí)行一次,而調(diào)用構(gòu)造器是對(duì)象實(shí)例化執(zhí)行的,每實(shí)例化一次對(duì)象,執(zhí)行一次。

    posted @ 2014-08-12 09:34 順其自然EVO 閱讀(202) | 評(píng)論 (0)編輯 收藏

    第一個(gè)公司的iOS項(xiàng)目總結(jié)

     第一個(gè)正式的universal項(xiàng)目差不多快要結(jié)束,總結(jié)一下,分享給大家。因?yàn)榭赡芪业谋容^具有代表性,如何從壓根不懂開(kāi)始做起。(分享的另外一個(gè)目的也是希望大家提提建議,畢竟只有互相交流中才能更快成長(zhǎng))
      -----------------------------------------------
      做項(xiàng)目前:
      零面向?qū)ο髮?shí)際項(xiàng)目經(jīng)驗(yàn),更不用說(shuō)透徹理解design pattern
      零iOS實(shí)際項(xiàng)目經(jīng)驗(yàn)
      只懂一點(diǎn)點(diǎn)的C和匯編代碼,其它如java、ruby、php、HTML5一點(diǎn)不沾邊,可以說(shuō)是不屬于互聯(lián)網(wǎng)的業(yè)余玩家
      項(xiàng)目的情況:
      做項(xiàng)目過(guò)程中,客戶需求變化極其頻繁和巨大,對(duì)代碼結(jié)構(gòu)的robust是一大挑戰(zhàn)。雖然本人特別討厭需求變動(dòng),但是在外,身不由己
      Universal項(xiàng)目,即是iPhone + iPad 的一個(gè)項(xiàng)目
      基本上這個(gè)項(xiàng)目涉及到了iOS的方方面面,麻雀雖小,但是五臟俱全
      關(guān)于程序結(jié)構(gòu)設(shè)計(jì)
      嘗試用面向?qū)ο蟮姆绞饺ピO(shè)計(jì)結(jié)構(gòu),但設(shè)計(jì)的時(shí)候流于形式,根據(jù)現(xiàn)有的一些best practice依葫蘆畫(huà)瓢,但實(shí)際上只有實(shí)踐了才知道,比如:
      1. 屬性: 什么時(shí)候用和為什么用屬性、如何保持屬性私有、self.的使用,屬性的內(nèi)存釋放;
      2. 成員變量和屬性的區(qū)別
      3. 方法:什么時(shí)候用類(lèi)方法和對(duì)象方法
      4. 好的設(shè)計(jì)真的是“增之一分則太長(zhǎng),減之一分則太短”;好的設(shè)計(jì)關(guān)系到以后重構(gòu)的方便性
      5. 解耦設(shè)計(jì):對(duì)象之間如何通訊,如何傳值,如何回傳,如何用好notification、delegate、KVO;如何保持對(duì)象的純潔(不受玷污)
      6. MVC中的M和C分離,一直覺(jué)得自己做的項(xiàng)目是小項(xiàng)目,而且一直認(rèn)為過(guò)于注重結(jié)構(gòu),會(huì)增加代碼量,但是實(shí)際上項(xiàng)目不分大小,好的設(shè)計(jì):
      能隨時(shí)應(yīng)對(duì)客戶的需求變化
      能自己看得懂自己寫(xiě)的代碼(改的多了,都看不懂自己的代碼了,這是最悲催)
      回歸測(cè)試,一旦客戶需求改變,亂糟糟的代碼更加亂,這樣回歸基本上是需要全部。好的設(shè)計(jì)可以把客戶需求改變帶來(lái)的回歸測(cè)試降低到最低
      關(guān)于面向?qū)ο笤O(shè)計(jì)
      之前從沒(méi)有面向?qū)ο笤O(shè)計(jì)的經(jīng)驗(yàn),所以第一次從這種角度去解決問(wèn)題。“實(shí)踐出真理”,無(wú)論你平時(shí)看多少書(shū),如果沒(méi)有實(shí)踐過(guò),真的是無(wú)法體會(huì)面向?qū)ο笤O(shè)計(jì)的:
      一切從面向?qū)ο蟪霭l(fā)設(shè)計(jì):類(lèi)、對(duì)象、(私有)方法、(私有)屬性
      所謂面向?qū)ο螅褪歉鶕?jù)現(xiàn)實(shí)世界中客觀存在的事物(即對(duì)象)出發(fā)來(lái)構(gòu)造軟件系統(tǒng)
      只有真正從面向?qū)ο笕ピO(shè)計(jì),幾個(gè)月甚至幾年后,你才能復(fù)盤(pán)你的代碼。以前一直覺(jué)得代碼復(fù)盤(pán)如同圍棋復(fù)盤(pán)絕對(duì)是天才才有的本領(lǐng),現(xiàn)在才明白,其實(shí)關(guān)鍵是:你要清楚的知道你的代碼用在了哪里,為什么用
      從面向?qū)ο蟪霭l(fā),不要覺(jué)得一個(gè)功能很簡(jiǎn)單一個(gè)方法就搞定,盡量用面向?qū)ο笕タ紤]。這是做項(xiàng)目過(guò)程中犯的最大的錯(cuò)誤
      關(guān)于ARC
      我是項(xiàng)目做了1個(gè)月后,才決定把項(xiàng)目從MRC轉(zhuǎn)到ARC,現(xiàn)在回頭看看,當(dāng)初真實(shí)明智,因?yàn)樵诘谝粋€(gè)月,內(nèi)存管理上的問(wèn)題和處理讓我很頭疼也很花時(shí)間。關(guān)于ARC
      沒(méi)有想象中的會(huì)比MRC性能差,ARC不是JAVA的垃圾回收,性能其實(shí)與MRC基本一致
      ARC中沒(méi)有明確的release操作,這時(shí)更需要注意內(nèi)存管理,比如在一個(gè)Controller中使用Gyro sensor的時(shí)候,這種操作是絕對(duì)不能賦值給局部變量的:[[CMMotionManager alloc]init]
      雖然ARC似乎能為你做很多事,但是有些事情自己解決還是自己解決,比如當(dāng)不需要用Gyro sensor時(shí),_motionManager = nil(此時(shí)如果不設(shè)置,則startDeviceMotionUpdatesToQueue中的更新會(huì)一直進(jìn)行);
      總之,對(duì)于ARC,難得糊涂中要“時(shí)刻保持覺(jué)醒”
      關(guān)于Perfomrance設(shè)計(jì)
      Coding真的是一點(diǎn)都來(lái)不得馬虎,以前一直覺(jué)得iOS性能強(qiáng)大,無(wú)須擔(dān)心性能,但是項(xiàng)目做下來(lái),一大痛苦之處就是性能不夠:
      應(yīng)用程序、UIViewController和UIView的生命周期的認(rèn)識(shí)如果不十分清楚,就很容易造成性能瓶頸
      大量的UIView插入移除操作會(huì)導(dǎo)致性能問(wèn)題
      UITableView和UIScrollView導(dǎo)致滑動(dòng)不順暢的best practice
      關(guān)于知識(shí)點(diǎn)
      成為一名優(yōu)秀Programmer需要豐富的經(jīng)驗(yàn)和知識(shí)面,但是知識(shí)永遠(yuǎn)是學(xué)習(xí)不完的,所以要抓核心和基本,個(gè)人覺(jué)得以下幾個(gè)知識(shí)點(diǎn)是iOS開(kāi)發(fā)必須的。至于有些比如CoreText、CoreImage等,其實(shí)等到需要用時(shí)再去學(xué)習(xí)也來(lái)得及。
      內(nèi)存管理,MRC和ARC
      多線程,iOS下有多種多線程實(shí)現(xiàn)方式,什么都應(yīng)該了解一下,但是除了dispatch需要精通,其它只需要看懂 (dispatch效率最高,使用最方便)
      數(shù)據(jù)庫(kù),無(wú)論是Core Data,F(xiàn)MDB還是基本的Sqlite,萬(wàn)事不離其中,掌握Sqlite和SQL基本語(yǔ)法是必須的
      UIViewController、UITableViewController 和應(yīng)用程序的生命周期
      看似簡(jiǎn)單但是很有深度的View之間的轉(zhuǎn)場(chǎng)處理,因?yàn)樯婕暗酱罅可芷冢鏿resentModalViewController, presentViewController, pushViewController, addSubview, removeFromSuperview, self.view....
      網(wǎng)絡(luò)處理相關(guān)的,如何請(qǐng)求JSON數(shù)據(jù),如何HTTP GET和POST
      旋轉(zhuǎn)處理,特別是iOS4、iOS5、iOS6的不同處理
      Debug的能力
      基本的設(shè)計(jì)模式:MVC、delegate、notification、target-action
      面向?qū)ο蟮暮诵乃枷耄纾翰灰杂脩魺o(wú)法使用或不感興趣的東西擾亂類(lèi)的公有接口、類(lèi)之間應(yīng)該零耦合、把不相關(guān)的信息放在另一個(gè)類(lèi)中
      不重復(fù)造輪子
      這個(gè)也不例外,iOS下的開(kāi)源framework都太多了,基本上你需要的都能在Github或者Stackoverflow上找得到,所以平時(shí):
      不要做井底之蛙,平時(shí)多了解開(kāi)源的框架
      框架適合就行,就像爭(zhēng)論AFNetwork和ASIHttpNetwork更棒沒(méi)有意義的。寫(xiě)程序的有兩類(lèi)人,一類(lèi)人追求技術(shù)極致,一類(lèi)人技術(shù)只是實(shí)現(xiàn)產(chǎn)品的一種手段,我就是后面這個(gè)
      關(guān)于開(kāi)源框架的學(xué)習(xí)
      這世界好的開(kāi)源框架太多了,給我10年都看不完,所以需要選擇,就像讀書(shū)不在于都多,而在于讀精,個(gè)人推薦如下。
      Three20 (其實(shí)我是不推薦的,因?yàn)樗^(guò)時(shí)了,但是因?yàn)樘詫毧蛻舳擞玫剑?/div>
      AFNetwork
      MBProgressHUD
      SDWebImage
      關(guān)于Continuous Improvement
      Six sigma中提到了持續(xù)改進(jìn),我們的能力提高也是這樣。通過(guò)讀好的開(kāi)源框架是最好的進(jìn)步方式。如何讀開(kāi)源框架,我們讀開(kāi)源框架的目的:
      其中的花式寫(xiě)法我們只是了解,不是我們的目的
      了解作者寫(xiě)框架的思路
      對(duì)比自己現(xiàn)有的,求改進(jìn)
     關(guān)于設(shè)計(jì)模式
      做項(xiàng)目前,把GOF的23種設(shè)計(jì)模式都看了一遍,項(xiàng)目做下了,體會(huì)到:
      單看設(shè)計(jì)模式的書(shū),純粹是無(wú)用;
      設(shè)計(jì)模式的核心在于平時(shí)的有意無(wú)意的使用,因?yàn)樗旧韥?lái)源于實(shí)際;
      能熟背23種設(shè)計(jì)模式固然是件好事,但是不能也不見(jiàn)得是壞事(反正我是記不住的)
      欲速則不達(dá)
      代碼之間往往只查一兩個(gè)字符,但性能和結(jié)局多半千差萬(wàn)別,因?yàn)轫?xiàng)目緊,壓力大,又是第一個(gè)項(xiàng)目,所以寫(xiě)代碼的時(shí)候,追求:"meet requirement,先滿足功能,再考慮代碼結(jié)構(gòu)",但是實(shí)際:
      需求無(wú)論大小,代碼結(jié)構(gòu)設(shè)計(jì)是必須的而且是第一位的,因?yàn)檫@關(guān)系到未來(lái)的改動(dòng),未來(lái)自己能否看懂;
      欲速則不達(dá),真是一個(gè)真理
      關(guān)于Best Practice的重要
      iOS已經(jīng)很成熟了,基本上,所有問(wèn)題都能找到答案,所有的需求都有現(xiàn)成的framework,或者只需要稍許改改。但是也正因?yàn)?#8220;萬(wàn)能的internet”,所以很多答案或者很多framework都是有問(wèn)題的,所以適時(shí)總結(jié)很重要:
      把常用的代碼或者容易錯(cuò)的代碼寫(xiě)到Xcode的snippet中
      要有自己的library,不是自己擺酷,而是知識(shí)需要積累,有些開(kāi)發(fā)中經(jīng)常會(huì)遇到的
      用好的framework。不流行的框架要注意是否用了私有方法(蘋(píng)果 will reject it)
      best practice,比如如何自定義TableCell,如何自定義Navigation bar
      不玩花的,不玩偏門(mén)的,寫(xiě)代碼就是規(guī)規(guī)矩矩,一切按照蘋(píng)果的best practice寫(xiě)
      面向?qū)ο蟮乃枷胗泻芏喔乓綍r(shí)要時(shí)刻提醒自己
      關(guān)于HTML5
      iOS原生與HTML5 WEB APP天生就是一對(duì)敵人,做HTML5的可以不懂iOS開(kāi)發(fā),但是做iOS開(kāi)發(fā)必須懂點(diǎn)HTML5:
      iOS應(yīng)用中一些“高度變化”或“性能要求不高”或“上線緊迫”的地方會(huì)用到UIWebView
      iOS原生與UIWebView的之間交互其實(shí)也可以很棒,甚至JSP交互
      HTML5是“可能”的未來(lái),世界都在談?wù)?/div>
      HTML5看似只有一個(gè)知識(shí)點(diǎn),但是其實(shí)要求比iOS原生開(kāi)都高:一個(gè)典型的移動(dòng)HTML5頁(yè)面 = JSP + HTML + CSS + JQuery + backbone.js。或者學(xué)習(xí)PhoneGap也是不錯(cuò)的注意。
      關(guān)于未來(lái):
      如何讓自己在最短的時(shí)間內(nèi)成為優(yōu)秀,這是每天都在思考的,因?yàn)閷?duì)比別人_大學(xué)+工作下來(lái)的多年工作經(jīng)驗(yàn),我是不懼任何優(yōu)勢(shì)的,但是既然入行,就必須做優(yōu)秀。所以選擇值得做的事尤其重要:
      看書(shū)沒(méi)用,實(shí)踐和Coding是提高能力的唯一途徑;
      做實(shí)際項(xiàng)目比自己玩玩靠譜十萬(wàn)倍
      壓力下工作成長(zhǎng)更快,所以不斷挑戰(zhàn)自己,人的潛力是無(wú)限的
      番茄工作法則比較適合我(每次集中做半個(gè)小時(shí))

    posted @ 2014-08-12 09:33 順其自然EVO 閱讀(2934) | 評(píng)論 (1)編輯 收藏

    目前流行的缺陷管理工具

     缺陷管理工具:
      1. Bugzilla
      2. Bugfree
      3. TestDirector (Quality Center)
      4. ClearQuest
      5. JIRA
      6. Mantis
      7. Bugzero
      8. BugTracker
      9. URTracker
      10.KisTracker
      11.TestLink
      12、JTrac
      13、BugNet
      14、BugOnline
      15、eTraxis
      一、Bugzilla(免費(fèi),跨平臺(tái))
      Bugzilla是一個(gè)Bug追蹤系統(tǒng)設(shè)計(jì)用來(lái)幫助你管理軟件開(kāi)發(fā)
      Bugzilla是一開(kāi)源Bug Tracking System,是專(zhuān)門(mén)為Unix定制開(kāi)發(fā)的。但是在windows平臺(tái)下依然可以成功安裝使用.
      Testopia是一款和Bugzilla集成到一起的test case management系統(tǒng).
      它的強(qiáng)大功能表現(xiàn)在以下幾個(gè)方面:
      1. 強(qiáng)大的檢索功能
      2. 用戶可配置的通過(guò)Email公布Bug變更
      3. 歷史變更記錄
      4. 通過(guò)跟蹤和描述處理Bug
      5. 附件管理
      6. 完備的產(chǎn)品分類(lèi)方案和細(xì)致的安全策略
      7. 安全的審核機(jī)制
      8. 強(qiáng)大的后端數(shù)據(jù)庫(kù)支持
      9. Web,Xml,Email和控制界面
      10. 友好的網(wǎng)絡(luò)用戶界面
      11. 豐富多樣的配置設(shè)定
      12. 版本間向下兼容
      二、BugFree(免費(fèi))
      BugFree是借鑒微軟的研發(fā)流程和Bug管理理念,使用PHP+MySQL獨(dú)立寫(xiě)出的一個(gè)Bug管理系統(tǒng)。簡(jiǎn)單實(shí)用、免費(fèi)并且開(kāi)放源代碼(遵循GNU GPL)。
      三、Quality Center(商業(yè),前身Mercury TestDirector ,跨平臺(tái))
      HP Quality Center; 提供了基于 Web 的系統(tǒng),可在廣泛的應(yīng)用環(huán)境下自動(dòng)執(zhí)行軟件質(zhì)量測(cè)試和管理。儀表盤(pán)技術(shù)使您可以了解驗(yàn)證功能和將業(yè)務(wù)流程自動(dòng)化,并確定生產(chǎn)中阻礙業(yè)務(wù)成果的瓶頸。HP Quality Center 使 IT 團(tuán)隊(duì)能夠在開(kāi)發(fā)流程完成前就參與應(yīng)用程序測(cè)試。這樣將縮短發(fā)布時(shí)間表,同時(shí)確保最高水平的質(zhì)量。
      企業(yè)級(jí)的軟件質(zhì)量解決方案。
      四、IBM Rational ClearQuest (商業(yè),跨平臺(tái))
      IBM Rational ClearQuest 是一款強(qiáng)大的軟件開(kāi)發(fā)測(cè)試工具。集成并自動(dòng)化軟件及系統(tǒng)開(kāi)發(fā)的業(yè)務(wù)過(guò)程。V7.0 提供增強(qiáng)的需求跟蹤、構(gòu)建跟蹤、企業(yè)測(cè)試管理,及部署跟蹤的功能。這提供了從開(kāi)發(fā)到部署的完整的審計(jì)跟蹤,并擴(kuò)展了跨生命周期的可追溯性。軟件增強(qiáng)了開(kāi)發(fā)流程并使之自動(dòng)化,同時(shí)還提高了軟件生命周期的可理解性、可預(yù)測(cè)性和可控制性。
      五、JIRA(商業(yè))
      JIRA是集項(xiàng)目計(jì)劃、任務(wù)分配、需求管理、錯(cuò)誤跟蹤于一體的商業(yè)軟件。
      JIRA功能全面,界面友好,安裝簡(jiǎn)單,配置靈活,權(quán)限管理以及可擴(kuò)展性方面都十分出色。
      JIRA創(chuàng)建的默認(rèn)問(wèn)題類(lèi)型包括New Feature、Bug、Task和Improvement四種,還可以自己定義,所以它也一是過(guò)程管理系統(tǒng)。
      Jira融合了項(xiàng)目管理、任務(wù)管理和缺陷管理,許多著名的開(kāi)源項(xiàng)目都采用了JIRA。
      JIRA 是目前比較流行的基于Java架構(gòu)的管理系統(tǒng),由于Atlassian公司對(duì)很多開(kāi)源項(xiàng)目實(shí)行免費(fèi)提供缺陷跟蹤服務(wù),因此在開(kāi)源領(lǐng)域,其認(rèn)知度比其他的產(chǎn)品要高得多,而且易用性也好一些。同時(shí),開(kāi)源則是其另一特色,在用戶購(gòu)買(mǎi)其軟件的同時(shí),也就將源代碼也購(gòu)置進(jìn)來(lái),方便做二次開(kāi)發(fā)。
      六、Mantis(開(kāi)源)
      Mantis是一個(gè)基于PHP技術(shù)的輕量級(jí)的缺陷跟蹤系統(tǒng),其功能與前面提及的JIRA系統(tǒng)類(lèi)似,都是以Web操作的形式提供項(xiàng)目管理及缺陷跟蹤服務(wù)。在功能上可能沒(méi)有JIRA那么專(zhuān)業(yè),界面也沒(méi)有JIRA漂亮,但在實(shí)用性上足以滿足中小型項(xiàng)目的管理及跟蹤。更重要的是其開(kāi)源,不需要負(fù)擔(dān)任何費(fèi)用。不過(guò)目前的版本還存在一些問(wèn)題,期待在今后的版本中能夠得以完善。
      七、Bugzero 免費(fèi)開(kāi)源,跨平臺(tái))
      BUGZERO? 是一個(gè)多功能,基于網(wǎng)絡(luò) (web-based) 并在瀏覽器 (browser) 下運(yùn)行的 Bug缺陷管理和跟蹤系統(tǒng) (bug tracking system),可用來(lái)記錄,跟蹤,并歸類(lèi)處理軟件開(kāi)發(fā)過(guò)程出現(xiàn)的 Bug 和硬件系統(tǒng)中存在的缺陷(defect)。 BUGZERO 也是一個(gè)完整的服務(wù)管理軟件,包括集成服務(wù)臺(tái)熱線流程管理(Help Desk),可用來(lái)記錄各種日常事務(wù),變更請(qǐng)求,和問(wèn)題報(bào)告,及追蹤和處理各種客戶訊問(wèn),反饋,和意見(jiàn)。
      BUGZERO 提供了一個(gè)可靠的中央數(shù)據(jù)庫(kù)使公司內(nèi)部團(tuán)隊(duì)成員以及外部客戶能在任何地點(diǎn)任何時(shí)間進(jìn)行協(xié)調(diào)和信息交流,并且使任何記錄都有據(jù)可查。它使你省時(shí)省力。BUGZERO 不但使用方便,而且功能齊全,變通性好,能夠靈活設(shè)置各種實(shí)際工作流程,滿足你特定的業(yè)務(wù)和產(chǎn)品環(huán)境下的需求。這種靈活、易用的缺陷跟蹤流程不僅增強(qiáng)了項(xiàng)目開(kāi)發(fā)的質(zhì)量,同時(shí)也提高了整個(gè)機(jī)構(gòu)的生產(chǎn)效率。
     八、BugTracker(免費(fèi)開(kāi)源,跨平臺(tái))
      Bugtracker是一個(gè)完整的bug/issue管理系統(tǒng).它使用Java Servlet作為web前臺(tái),MySQL數(shù)據(jù)庫(kù)作為后臺(tái)。
      九、JTrac(開(kāi)源)
      JTrac是一個(gè)開(kāi)源且可高度配置的問(wèn)題追蹤的Web應(yīng)用程序。它是一個(gè)一般性問(wèn)題,跟蹤網(wǎng)絡(luò)應(yīng)用程序,可方便地實(shí)現(xiàn)定制,增加自定義字段和下拉式。其特點(diǎn)包括可定制的工作流程,實(shí)地一級(jí)的權(quán)限,電子郵件集成,文件附件和詳細(xì)的歷史觀點(diǎn)。
      十、BugNet(開(kāi)源)
      BugNet是一個(gè)不錯(cuò)的開(kāi)源bug跟蹤和項(xiàng)目管理系統(tǒng)
      十一、BugOnline(開(kāi)源)
      BugOnline 是一個(gè)開(kāi)源的BUG管理系統(tǒng)。其功能強(qiáng)大,易于使用。
      基于asp.net2.0 ,sql server 2005(包括Express 版),Ajax等技術(shù).
      BugOnline 的一些特性:
      在線消息及E-mail自動(dòng)通知功能。有新Bug及Bug分配給用戶同時(shí)將自動(dòng)通知用戶。
      優(yōu)秀的人員分配,工作量統(tǒng)計(jì)功能。
      居于項(xiàng)目角色的權(quán)限管理,工作規(guī)劃,流程化。
      Bug狀態(tài)統(tǒng)計(jì),便于掌控項(xiàng)目進(jìn)度。
      基于SSL的數(shù)據(jù)傳輸,確保數(shù)據(jù)不被截取,保證安全性。(也可設(shè)定為非SSL)
      強(qiáng)大的報(bào)表功能。
      十二、eTraxis(開(kāi)源)
      eTraxis是基于網(wǎng)頁(yè)的免費(fèi)bug跟蹤系統(tǒng)。主要特點(diǎn)是:完全自定義模板,先進(jìn)的過(guò)濾器, LDAP支持,電子郵件通知,訂閱報(bào)刊,提醒,靈活的權(quán)限管理,圖形化的項(xiàng)目指標(biāo)等。
      十三、URTracker(商業(yè))
      URTracker 是一款通用的流程化的問(wèn)題跟蹤管理軟件。它可以:
      幫助您集中管理各種類(lèi)型的問(wèn)題、工作任務(wù)、人員交互等事務(wù);
      跟蹤每個(gè)事務(wù)的處理過(guò)程;
      控制問(wèn)題處理的流程;
      提供一個(gè)有效的協(xié)作平臺(tái),簡(jiǎn)化團(tuán)隊(duì)成員的交互,提升溝通效率;
      積累知識(shí)信息;
      幫助您進(jìn)行統(tǒng)計(jì)和分析;
      十四、KisTracker
      KisTracker一款bug跟蹤管理軟件(原名叫:iTracker),功能強(qiáng)大,易于使用,是基于WEB方式的協(xié)同工作軟件.
      它用于幫助公司和團(tuán)隊(duì)跟蹤工作中的問(wèn)題,管理和記錄這些問(wèn)題的處理過(guò)程.可以應(yīng)用于:
      1.產(chǎn)品BUG跟蹤
      2.任務(wù)跟蹤
      3.服務(wù)跟蹤
      4.各種處理問(wèn)題跟蹤
      十五、TestLink(開(kāi)源)
      TestLink用于進(jìn)行測(cè)試過(guò)程中的管理,通過(guò)使用TestLink提供的功能,
      可以將測(cè)試過(guò)程從測(cè)試需求、測(cè)試設(shè)計(jì)、到測(cè)試執(zhí)行完整的管理起來(lái),
      同時(shí),它還提供了好多種測(cè)試結(jié)果的統(tǒng)計(jì)和分析,使我們能夠簡(jiǎn)單的開(kāi)始測(cè)試工作和分析測(cè)試結(jié)果。
      TestLink 是sourceforge的開(kāi)放源代碼項(xiàng)目之一。作為基于web的測(cè)試管理系統(tǒng),TestLink的主要功能包括:測(cè)試需求管理 測(cè)試用例管理測(cè)試用例對(duì)測(cè)試需求的覆蓋管理 測(cè)試計(jì)劃的制定 測(cè)試用例的執(zhí)行 大量測(cè)試數(shù)據(jù)的度量和統(tǒng)計(jì)功能。

    posted @ 2014-08-12 09:31 順其自然EVO 閱讀(569) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共394頁(yè): First 上一頁(yè) 67 68 69 70 71 72 73 74 75 下一頁(yè) Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    • 隨筆 - 3936
    • 文章 - 404
    • 評(píng)論 - 179
    • 引用 - 0

    常用鏈接

    留言簿(55)

    隨筆分類(lèi)

    隨筆檔案

    文章分類(lèi)

    文章檔案

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲a在线视频视频| 亚洲一区二区三区四区视频| 亚洲成av人片在线看片| 产传媒61国产免费| 114级毛片免费观看| 国产一级特黄高清免费大片| 亚洲Av无码专区国产乱码DVD| 亚洲精品自偷自拍无码| 两个人日本WWW免费版| 国产在线观看免费视频播放器| 久久亚洲国产成人精品性色| 免费播放国产性色生活片| 成人黄页网站免费观看大全| 亚洲AV无码久久精品成人| 国产一级淫片a免费播放口| 中国一级特黄的片子免费| 亚洲无线一二三四区手机| 亚洲一区二区三区亚瑟| 在线观看免费高清视频| 亚洲最新视频在线观看| 亚洲精品免费在线视频| 国产成人精品日本亚洲直接| 99免费观看视频| 亚洲中文字幕无码中文字在线| 亚洲精品GV天堂无码男同| 中国人xxxxx69免费视频| 亚洲国产午夜电影在线入口| 日日麻批免费40分钟无码| 亚洲第一页在线播放| 99在线免费观看视频| 亚洲国产精品久久丫| 成人免费无码大片a毛片软件| 亚洲欧洲av综合色无码| 午夜亚洲av永久无码精品| 亚洲另类自拍丝袜第五页| 亚洲电影日韩精品| 午夜亚洲国产精品福利| 国产免费卡一卡三卡乱码| 一级免费黄色大片| 亚洲精品视频在线观看你懂的 | 亚洲欧美日韩一区二区三区 |