當前位置:首頁 » 編程軟體 » mock重新編譯

mock重新編譯

發布時間: 2023-05-16 01:01:58

❶ 虛擬模擬提交實驗數據失敗404

組件沒有引入mock文件,應該重新引入。
虛擬模擬提交實驗數據失敗404,是因為請求的組件沒有引入mock文件,所以才會出現這樣的情況,只要出現引入困差就可以了。
404指的是網站出現錯誤,是錯誤代碼,意思是伺服器簡茄將無法正確提供有效汪咐皮信息。

❷ flutter 反編譯

>You are building a fat APK that includes binaries for android-arm, android-arm64.

>If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to rece the APK size.

>    To generate an app bundle, run:

>        flutter build appbundle --target-platform android-arm,android-arm64

>        Learn more on: https://developer.android.com/guide/app-bundle

>    To split the APKs per ABI, run:

>        flutter build apk --target-platform android-arm,android-arm64 --split-per-abi

>        Learn more on:  https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split

>Initializing gradle...                                              2.3s

>Resolving dependencies...                                          14.2s

>Running Gradle task 'assembleRelease'...                                                  ע: E:\work_tool\flutter\.pub-cache\hosted\pub.flutter-io.cn\connectivity-0.4.4\android\src\main\java\io\flutter\plugins\connectivity\ConnectivityPlugin.javaʹ�û򸲸����ѹ�ʱ�� API��

>ע: �й���ϸ��Ϣ, ��ʹ�� -Xlint:deprecation ���±��롣

>ע: E:\work_tool\flutter\.pub-cache\hosted\pub.flutter-io.cn\url_launcher-5.1.3\android\src\main\java\io\flutter\plugins\urllauncher\WebViewActivity.javaʹ

>�û򸲸����ѹ�ʱ�� API��

>ע: �й���ϸ��Ϣ, ��ʹ�� -Xlint:deprecation ���±��롣

>Calling mockable JAR artifact transform to create file: C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\android.jar\\android.jar with input E:\work_tool\sdk\android-sdk-windows\platforms\android-28\android.jar

>Calling mockable JAR artifact transform to create file: C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\android.jar\\android.jar with input E:\work_tool\sdk\android-sdk-windows\platforms\android-27\android.jar

>Request to incrementing alive workforce from 0. Current workforce (dead or alive) 0

>thread-pool size=4

>ProGuard, version 6.0.3

>Reading input...

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\flutter.jar\\jetified-flutter.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\app\intermediates\flutter\release\libs.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\localbroadcastmanager-1.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\work-runtime-2.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\fragment-1.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\room-runtime-2.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\room-runtime-2.1.0.aar\\jars\libs\room-common-java8-2.1.0.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\viewpager-1.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\loader-1.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\activity-1.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\customview-1.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\core-1.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\versionedparcelable-1.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\androidx.collection\collection\1.1.0\\collection-1.1.0.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\lifecycle-livedata-2.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\lifecycle-livedata-core-2.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\core-runtime-2.0.1.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\androidx.room\room-common\2.1.0\\room-common-2.1.0.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\sqlite-framework-2.0.1.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\sqlite-2.0.1.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\lifecycle-service-2.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\lifecycle-runtime-2.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\lifecycle-viewmodel-2.1.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\transforms-1\files-1.1\savedstate-1.0.0.aar\\jars\classes.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\androidx.lifecycle\lifecycle-common\2.1.0\\lifecycle-common-2.1.0.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\androidx.arch.core\core-common\2.1.0\\core-common-2.1.0.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\androidx.annotation\annotation\1.1.0\\annotation-1.1.0.jar] (filtered)

>Reading program jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\com.google.guava\listenablefuture\1.0\\listenablefuture-1.0.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\flutter_downloader\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\shared_preferences\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\url_launcher\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\sqflite\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\connectivity\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\path_provider\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\package_info\intermediates\intermediate-jars\release\classes.jar] (filtered)

>Reading program directory [F:\dartSpace\flutter\jiddspace\nfc\build\app\intermediates\javac\release\compileReleaseJavaWithJavac\classes] (filtered)

>Reading program jar [F:\dartSpace\flutter\jiddspace\nfc\build\app\intermediates\transforms\mergeJavaRes\release\0.jar] (filtered)

>Reading library jar [C:\Users\Administrator\.gradle\caches\moles-2\files-2.1\androidx.annotation\annotation\1.0.0\\annotation-1.0.0.jar] (filtered)

>Reading library jar [E:\work_tool\sdk\android-sdk-windows\platforms\android-28\android.jar]

>Reading library jar [E:\work_tool\sdk\android-sdk-windows\build-tools\28.0.3\core-lambda-stubs.jar]

>Reading library jar [E:\work_tool\sdk\android-sdk-windows\platforms\android-28\optional\org.apache.http.legacy.jar]

>Reading library jar [E:\work_tool\sdk\android-sdk-windows\platforms\android-28\optional\android.test.mock.jar]

>Reading library jar [E:\work_tool\sdk\android-sdk-windows\platforms\android-28\optional\android.test.base.jar]

>Reading library jar [E:\work_tool\sdk\android-sdk-windows\platforms\android-28\optional\android.test.runner.jar]

>Initializing...

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced method 'android.graphics.Insets getSystemGestureInsets()' in library class android.view.WindowInsets

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.embedding.android.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.view.FlutterView: can't find referenced method 'android.graphics.Insets getSystemGestureInsets()' in library class android.view.WindowInsets

>Warning: io.flutter.view.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.view.FlutterView: can't find referenced class android.graphics.Insets

>Note: io.flutter.view.AccessibilityViewEmbedder$ReflectionAccessors: can't find dynamically referenced class android.util.LongArray

>Warning: io.flutter.view.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.view.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.view.FlutterView: can't find referenced class android.graphics.Insets

>Warning: io.flutter.view.FlutterView: can't find referenced class android.graphics.Insets

>Note: there were 1 unresolved dynamic references to classes or interfaces.

>      You should check if you need to specify additional program jars.

>      (http://proguard.sourceforge.net/manual/troubleshooting.html#dynamicalclass)

>Warning: Exception while processing task java.io.IOException: Please correct the above warnings first.

>Thread(Tasks limiter_1): destruction

>Warning: there were 12 unresolved references to classes or interfaces.

>        You may need to add missing library jars or update their versions.

>        If your code works fine without the missing classes, you can suppress

>        the warnings with '-dontwarn' options.

>        (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)

>Warning: there were 2 unresolved references to library class members.

>        You probably need to update the library versions.

>        (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)

>

>FAILURE: Build failed with an exception.

>

>* What went wrong:

>Execution failed for task ':app:'.

>> Job failed, see logs for details

>

>* Try:

>Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

>

>* Get more help at https://help.gradle.org

>

>BUILD FAILED in 4m 23s

>Running Gradle task 'assembleRelease'...

>Running Gradle task 'assembleRelease'... Done                    264.4s (!)

>*******************************************************************************************

>The Gradle failure may have been because of AndroidX incompatibilities in this Flutter app.

>See https://goo.gl/CP92wY for more information on the problem and how to fix it.

>*******************************************************************************************

>Gradle task assembleRelease failed with exit code 1

❸ Mockito和嵌套的方法調用問題,怎麼解決

Jmock和Mockito是常用的mock工具,Jmock功能相當強大,也比較容易用。Mockito 在處理多層嵌套時比較麻煩,下面說明了這種場景的主要用法。不過建議不是用jmock。

packagecom.jd.test;

importstaticorg.junit.Assert.assertEquals;
importstaticorg.mockito.Matchers.anyLong;
importstaticorg.mockito.Mockito.when;

importjavax.annotation.Resource;

importorg.junit.Before;
importorg.junit.Test;
importorg.junit.runner.RunWith;
importorg.mockito.InjectMocks;
importorg.mockito.Mock;
importorg.mockito.MockitoAnnotations;
importorg.mockito.Spy;
importorg.springframework.test.context.ContextConfiguration;
importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;

importcom.jd.test.service.CustomerBusiness;
importcom.jd.test.service.FeeBusiness;
importcom.jd.test.service.OrderBusiness;
importcom.jd.test.service.ProctBusiness;
importcom.jd.test.service.impl.FeeBusinessImpl;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/spring-config.xml")
publicclassMockitoTest{


@Resource
@InjectMocks
;

@Mock
;

@Resource
@InjectMocks
;

@Spy
privateFeeBusinessfeeBusiness=newFeeBusinessImpl();


@Before
publicvoidsetup(){
MockitoAnnotations.initMocks(this);
}

/**
*自動注入mock管理的bean.解決二層和多層bean嵌套的部分mock場景。雹游簡即injectProctBusiness->customerBusiness->feeBusiness時,如果想mockfeeBusiness中的某個方法.
*磨返
* @Resource
@InjectMocks
;

@Resource
@InjectMocks
;

@Spy
privateFeeBusinessfeeBusiness=newFeeBusinessImpl();
*
*@InjectMocks標簽會自動填充帶@Spy和@Mock標簽的bean.
*@Spy被它代理的bean,默認執行原生方法。但可以在後期mock想要的方法。
*@Mock相當於mockito幫助簡單的實例化bean,因此無法執行原生方法。適用於整個bean都mock,如源褲DAO。
*
*同時可以結合spring一起管理bean.對bean的管理應該是spring先進行一系列的如初始化bean操作,然後mockito會引用spring生成的bean,並對bean里的指定field進行重新注入。以達到實現部分mock功能。
*/
@Test
publicvoidinjectClass(){

when(feeBusiness.getFee(anyLong())).thenReturn("spyinject");

assertEquals(injectProctBusiness.getCustomerName(1),"proctBusinessimpl->null");
assertEquals(injectProctBusiness.getCustomerPhone(2),"proctBusinessimpl->CustomerBusinessImpl->2");
assertEquals(injectProctBusiness.getOrderFee(3),"proctBusinessimpl->CustomerBusinessImpl->spyinject");


}

}

❹ 在組合模式中實現訪問者(Visitor)模式

本文從一個給定的實現了組合(Composite)模式的例子開始 說明怎麼在這個數據結構上實現業務邏輯代碼 依次介紹了非面向對象的方式 在組合結構中加入方法 使用訪問者(Visitor)模式以及用改進後的訪問者(Visitor)模式來實現相同的業務邏輯代碼 並且對於每種實現分別給出了優缺點

讀者定位於具有Java程序開發和設計模式經驗的開發人員

讀者通過本文可以學到如何在組合(Composite)模式中實現各種不同的業務方法及其優缺點

組合(Composite)模式

組合模式是結構型模式中的一種 GOF的《設計模式》一書中對使用組合模式的意圖描述如下 將對象組合成樹形結構以表示 部分 整體 的層次結構 Composite使得用戶對單個對象和組合對象的使用具有一致性

組合模式應用廣泛 根據GOF中對組合模式的定義 Composite模式一般由Component介面 Leaf類和Composite類組成 現在需要對一個軟體產品管理系統的實體建模 某公司開發了一系列軟體集(SofareSet) 包含了多橘正種品牌(Brand)的軟體產品 就象IBM提供了Lotus WebsPhere等品牌 每個品牌下面又有各種產品(Proct) 如IBM的Lotus下面有Domino Server/Client產品等 建模後的類圖如下(代碼可以參見隨本文帶的附件中 包 test entity下所有的源文件)

如圖所示

( )介面SofareComponent就是對應於組合模式中的Component介面 它定義了所有類共有介面的預設行為

( )AbsSofareComposite類對應於Composite類 並且是抽象類 所有可以包含子節點的類都擴展這個類 這個類的主要功能是用來存儲子部件 實現了介面中的方法 部分可以重用的代碼寫在此類中

( )SofareSet類繼承於AbsSofareComposite類 對應於軟體集 軟體集下直接可以包含品牌(Brand) 也可以直接包含不屬於任何品牌的產品(Proct)

( )Brand類繼承於AbsSofareComposite類 對應於品牌 包含了品牌名屬性 並且用來存儲Proct類的實例

( )Proct類就是對應的Leaf類 表示葉子節點 葉子節點沒有子節點

用不同的方法實現業務邏輯

數據結構建立好之後 需要在這個數據結構上添加方法實現圓氏悔業務邏輯 比如現在的這個例子中 有這樣的需求 給定一些用戶選擇好的產品 需要計算出這些選中後軟體的總價格 下面開始介紹如何使用各種不同的方法來實現這個業務邏輯

非面向對象的編程方式

這種方式下 編程思路最簡單 遍歷SofareSet實例中的所有節點 如果遍歷到的當前對象是Proct的話就累加 否則繼續遍歷下一層直到全部遍歷完畢 代碼片斷如下

    /** *取得某個SofareComponent對象下面所有Proct的價格 *@parambrand *@return */ public double getTotalPrice(){ SofareComponenttemp=sofareComponent; double totalPrice= ; //如果傳入的實例是SofareSet的類型 if (temp instanceof SofareSet){ Iteratorit=((SofareSet)sofareComponent) getChilds() &erator(); while (it hasNext())核山{ //遍歷 temp=(SofareComponent)it next(); //如果子對象是Proct類型的 直接累加 if (temp instanceof Proct){ Proctproct=(Proct)temp; totalPrice+=proct getPrice(); } else if (temp instanceof Brand){ //如果子對象是Brand類型的 則遍歷Brand下面所有的產品並累加 Brandbrand=(Brand)temp; totalPrice+=getBrandPrice(brand); } } } else if (temp instanceof Brand){ //如果傳入的實例是SofareSet的類型 則遍歷Brand下面所有的產品並累加 totalPrice+=getBrandPrice((Brand)temp); } else if (temp instanceof Proct){ //如果子對象是Proct類型的 直接返回價格 return ((Proct)temp) getPrice(); } return totalPrice; } /** *取得某個Brand對象下面所有Proct的價格 *@parambrand *@return */ private double getBrandPrice(Brandbrand){ IteratorbrandIt=brand getChilds(erator(); double totalPrice= ; while (brandIt hasNext()){ Proctproct=(Proct)brandIt next(); totalPrice+=proct getPrice(); } return totalPrice; }

這段代碼的好處是實現業務邏輯的時候無需對前面已經定好的數據結構做改動 並且效率比較高 缺點是代碼凌亂而且頻繁使用了instanceof判斷類型和強制類型轉換 代碼的可讀性不強 如果層次多了代碼就更加混亂

面向對象的編程方式(將計算價格的方法加入數據結構中)

下面我們採用面向對象的方式 可以這么做 在介面SoftWareComponent中加入一個方法 名叫getTotalPrice 方法的聲明如下

    /** *返回該節點中所有子節點對象的價格之和 *@return */ public double getTotalPrice();
由於類Brand和SofareSet都繼承了AbsSofareComposite 我們只需在類AbsSofareComposite中實現該方法getTotalPrice方法即可 如下
    public double getTotalPrice(){ Iteratorit=erator(); double price= ; while (it hasNext()){ =(SofareComponent)it next(); //自動遞歸調用各個對象的getTotalPrice方法並累加 price+=sofareComponent getTotalPrice(); } return price; }
在Proct類中實現如下
    public double getTotalPrice(){ return price; }
在外面需要取得某個對象的總價格的時候只需這樣寫(在本文的例子 test business SofareManager中可以找到這段代碼)
    //getMockData()方法返回數據 SofareComponentdata=getMockData(); //只需直接調用data對象的getTotalPrice方法就可以返回該對象下所有proct對象的價格 double price=data getTotalPrice(); //找到某個對象後直接調用其getTotalPrice方法也可以返回總價格 price=data findSofareComponentByID( id ) getTotalPrice();

現在把業務邏輯的實現都放在了數據結構中(組合模式的結構中) 好處很明顯 每個類只管理自己相關的業務代碼的實現 跟前面舉的面向過程方式的實現方式相比 沒有了instanceof和強制類型轉換 但是不好的地方是如果需要增加新的業務方法的話就很麻煩 必須在介面SoftWareComponent中首先聲明該方法 然後在各個子類中實現並且重新編譯

使用訪問者模式

使用訪問者模式就能解決上面提到的問題 如果要經常增加或者刪除業務功能方法的話 需要頻繁地對程序進行重新實現和編譯 根據面向對象設計原則之一的SRP(單一職責原則)原則 如果一個類承擔了多於一個的職責 那麼引起該類變化的原因就會有多個 就會導致脆弱的設計 在發生變化時 原有的設計可能會遭到意想不到的破壞 下面我們引入了一個叫做Visitor的介面 該介面中定義了針對各個子類的訪問方法 如下所示

    public interface Visitor{ public void visitBrand(Brandbrand); public void visitSofareSet(SofareSetsofareSet); public void visitProct(Proctproct); }
visitBrand方法是訪問Brand對象節點的時候用的 剩下的方法依次類推 並在介面SofareComponent中增加一個方法
    public void accept(Visitorvisitor);
在SofareSet中實現介面中的accept方法 首先直接調用Visitor介面中的visitSofareSet方法 傳入的參數是本身對象 然後遞歸調用子對象的accept方法
    public void accept(Visitorvisitor){ visitor visitSofareSet( this ); Iteratorit=erator(); while (it hasNext()){ SofareComponentponent=(SofareComponent)it next(); ponent accept(visitor); } }
在Brand中實現介面中的accept方法 首先直接調用Visitor介面中的visitBrand方法 傳入的參數是本身對象 然後遞歸調用子對象的accept方法
    public void accept(Visitorvisitor){ visitor visitBrand( this ); Iteratorit=erator(); while (it hasNext()){ SofareComponentponent=(SofareComponent)it next(); ponent accept(visitor); } }
其實在上面的兩個類的實現中可以將遍歷子節點並調用其accept方法的代碼寫到父類AbsSofareComposite中的某個方法中 然後直接調用父類中的這個方法即可 這里為了解釋方便分別寫在了兩個子類中 在Proct中實現介面中的accept方法 直接調用Visitor介面的visitProct方法即可
    public void accept(Visitorvisitor){ visitor visitProct( this ); }
下面需要實現Visitor介面 類名是CaculateTotalPriceVisitor 實現了計算總價格的業務邏輯 實現代碼如下所示
    public class CaculateTotalPriceVisitor implements Visitor{ private double totalPrice; public void visitBrand(Brandbrand){ } public void visitSofareSet(SofareSetsofareSet){ } public void visitProct(Proctproct){ //每次在組合的結構中碰到Proct對象節點的時候 就會調用此方法 totalPrice+=proct getPrice(); } public double getTotalPrice(){ return totalPrice; } }
上面那段代碼中 首先在類內定義一個總價格的屬性 由於Brand和SofareSet都沒有價格 因此在實現中 只需在visitProct方法中累加totalPrice即可 在外面如果需要計算總價格的話這樣寫(在本文的例子 test business SofareManager中可以找到這段代碼)
    //建立一個新的Visitor對象 = new CaculateTotalPriceVisitor(); //將該visitor對象傳到結構中 data accept(visitor); //調用visitor對象的getTotalPrice()方法就返回了總價格 double price=visitor getTotalPrice();

下面是它的時序圖 在類SofareManager中的main方法中 調用軟體集對象(data)的accept方法 並將生成的visitor對象傳給它 accept方法開始遞歸調用各個子對象的accept方法 如果當前的對象是SofareSet的實例 則調用visitor對象visitSofareSet方法 在visitor對象中對該節點的數據進行一些處理 然後返回 依次類推 遍歷到Brand對象和Proct對象也與此類似 當前的邏輯是計算軟體產品的總價格 因此當遍歷到Proct對象的時候 取出產品的價格並且累加 最後當結構遍歷完畢後 調用visitor對象的getTotalPrice方法返回給定軟體集對象的(data)的總的價格 如果需要加入一個新的計算邏輯 只實現Visitor介面 並且將該類的實例傳給data對象的accept方法就可以實現不同的邏輯方法了

點擊小圖看大圖

我們可以看到通過訪問者模式很好地解決了如何加入新的業務代碼而無需重新改動 編譯既有代碼 但是該模式也不是沒有缺點 如果在組合模式中結構加入新的子類的話會導致介面Visitor也跟著改動 導致所有Visitor的子類都需要實現新增的方法 因此這種訪問者模式適合於結構不經常變動的情況

改進訪問者模式

前面我們說到了如何使用Visitor模式及使用該模式後的優缺點 下面舉具體的例子說明 假設現在客戶提出了一個產品集(ProctSet)的概念 隨著公司軟體版本的增多 需要將同一個版本的產品(Proct)都放到產品集(ProctSet)中 而一個品牌包含有多個產品集 因為現在組合結構中增加了一個節點 所以在Visitor介面中也必須隨之增加一個叫做visitProctSet的方法 並且會導致原有系統中所有已經實現了Visitor介面的類都需要重新實現並編譯 用Java的反射機制可以解決這個問題

使用Java的Method Reflection機制實現訪問者模式

首先我們需要改變一下Visitor介面 介面名叫做ReflectionVisitor 如下所示

    public interface ReflectionVisitor{ /** *定義了一個訪問節點的方法 *@paramsofareComposite */ public void visitSofareComposite( Object sofareComposite); }

在現在的介面的方法里 能接受任意的對象(參數是Object)

下面實現介面ReflectionVisitor 名叫ReflectionVisitorImpl 代碼如下所示

    public class ReflectionVisitorImpl implements ReflectionVisitor{ public void visitSofareComposite( Object sofareComposite){ //判斷是否是null if (sofareComposite== null ){ throw new NullPointerException ( Thevisitnodeshouldnotbenull! ); } //組裝class數組 即調用動態方法的時候參數的類型 Class []classes= new Class []{sofareComposite getClass()}; //組裝與class數組相對應的值 Object []objects= new Object []{sofareComposite}; try { //查找visit方法 Methodm=getClass() getMethod( visit classes); //調用該方法 m invoke( this objects); } catch ( NoSuchMethodException e){ //沒有找到相應的方法 System out println( : +sofareComposite getClass()); } catch ( Exception e){ //發生了別的異常 System out println( ); e printStackTrace(); } } }

這段代碼首先判斷傳入的對象是否是空指針 然後創建class數組和object數組 然後用getMethod方法取得方法名是 visit 方法的參數是 對象sofareComposite對應的類 的方法 最後調用該方法 調用該方法的時候可能會發生NoSuchMethodException異常 發生這個異常就表明它的子類或者當前類中沒有與參數中傳入相對應的visit方法

下面再來寫新版本Visitor類 擴展剛寫好的那個ReflectionVisitorImpl類 名叫 如下所示

    public class extends ReflectionVisitorImpl{ private double totalPrice; public void visit(Proctproct){ totalPrice+=proct getPrice(); } public void visit(SofareSetsofareSet){ System out println( Nopriceforsofareset ); } public double getTotalPrice(){ return totalPrice; } }
代碼中聲明了兩個visit方法(因為在類ReflectionVisitorImpl中 查找名為visit 參數與傳進去的對象匹配的的方法) 一個是給Proct的 另外一個是給SofareSet的 在這里SofareSet中並沒有價格 只需當前的對象是類Proct的實例的時候將價格累加即可 如果在組合模式的結構中增加了新的類 只需要在ReflectionVisitorImpl的擴展類中聲明一個visit方法 該方法的參數是新增加的類 對於文中的例子 只需增加下面的一個方法
    public void visit(ProctSetproctSet){ //實現的代碼 }

在組合結構的介面SofareComponent中改一下accept方法 參數是修改後的Visitor介面 如下所示

public void accept(ReflectionVisitor visitor);

由於在類SofareSet Brand和ProctSet中實現上面accept方法的代碼都一樣 因此把代碼抽象到上層共有的抽象類AbsSofareComposite中 如下所示

    public void accept(ReflectionVisitorvisitor){ visitor visitSofareComposite( this ); Iteratorit=erator(); while (it hasNext()){ SofareComponentponent=(SofareComponent)it next(); //遞歸調用子對象的accept方法 ponent accept(visitor); } }
現在如果想在外面要調用的話 代碼如下所示(在本文的例子 test business SofareManager中可以找到這段代碼)
    //建立一個新的Visitor對象 reflectionVisitor = new (); //將該visitor對象傳到結構中 data accept(reflectionVisitor); //調用visitor對象的getTotalPrice()方法就返回了總價格 double price=reflectionVisitor getTotalPrice();

另外由於沒有實現Brand類的visit方法 在組合結構遍歷到Brand的節點的時候會拋出NoSuchMethodException異常 就是沒有關於該節點方法的實現 在當前的程序中會列印出一句話

You did not implement the visit method for class:class test entity Brand

如果運行程序時發生了別的異常 請參見相應的Java API文檔

在現在的改進後的訪問者模式中 如果在組合的結構中新增或刪除節點並不會對已經實現了的Visitor產生任何影響 如果新增了業務方法 只需擴展類ReflectionVisitorImpl就可以了 因此很好地解決了訪問者模式的問題

改進訪問者模式實現與既有代碼對接

到現在為止 改進後的訪問者模式好像已經很好地解決了所有出現的問題 但是考慮到有下面的這種情況 現在需要寫一個JSP的標簽庫(TagLib) 這個標簽庫還必須具有Visitor的功能(就是需要有遍歷節點的功能) 可以將節點的內容根據需要列印到HTML頁面中 由於標簽本身需要繼承相應的類(如TagSupport) 如果繼續使用上面提供的方法將無法實現 因為Java不允許多重繼承 不過我們可以將原有ReflectionVisitorImpl的代碼再改進一下以解決這種情況 新的Visitor的實現類叫NewReflectionVisitorImpl 代碼如下所示

    public class NewReflectionVisitorImpl implements ReflectionVisitor{ //實現visit方法的類 private Object targetObject; //構造方法 傳入實現了visit方法的類 public NewReflectionVisitorImpl( Object targetObject){ if (targetObject== null ) throw new NullPointerException ( ! ); this targetObject=targetObject; } public void visitSofareComposite( Object sofareComposite){ //……與上個例子相同 try { //從目標的對象中查找visit方法 Methodm=targetObject getClass() getMethod( visit classes); //調用該方法 m invoke(targetObject objects); } catch ( NoSuchMethodException e){ //……與上個例子相同 } catch ( Exception e){ //……與上個例子相同 } } }
該類的實現與上面的實現差不多 多了一個構造函數 在該構造函數的參數中傳入實現了visit方法的類 並且維護了指向該類的一個引用 另外最重要的地方是下面的兩行代碼
    //從目標的對象中查找visit方法 Methodm=targetObject getClass() getMethod( visit classes); //調用該方法 m invoke(targetObject objects);

本來的代碼中從本身的類及其子類中查找visit方法 而現在是從維護的目標類中查找visit方法

現在需要寫Tag類 這個類擴展了TagSupport類 如下所示(為說明的方便 隨本文的例子提供了一個模擬的TagSupport類)

    public class MyTag extends TagSupport{ = null ; private double totalPrice= ; public int doEngTag(){ //創建一個visitor對象 並且將本身傳入visitor對象中 ReflectionVisitorvisitor= new NewReflectionVisitorImpl( this ); //遍歷結構 sofareComponent accept(visitor); //列印出價格 out println(totalPrice); return ; } //實現了針對Proct的visit方法 public void visit(Proctproct){ totalPrice+=proct getPrice(); } public void visit(Brandbrand){ out println(brand getId()+brand getDescription()); } //別的代碼請參見隨本文帶的源程序 …… }
如果想測試上面寫的那段代碼 (在本文的例子 test business SofareManager中可以找到這段代碼))如下所示
    //getMockData()方法返回數據 SofareComponentdata=getMockData(); MyTagmyTag= new MyTag(); myTag setSofareComponent(data); //計算總價格 並列印出來 myTag doEngTag();

可以看到通過Java的反射機制很好地解決了多重繼承的問題 使該訪問者模式能夠更好地應用於你的應用中 另外可以看到 那些visit方法所在的類已經不是實現了介面ReflectionVisitor 可以說是訪問者模式在Java語言的支持下的一種特殊實現

如果擔心引入類反射機制後帶來的效率問題 你可以將Method對象通過某種方式緩沖起來 這樣不會每次從傳入的對象中找visit方法 可以部分地提高效率

結論

lishixin/Article/program/Java/gj/201311/11152

❺ 使用MOCK對象進行單元測試

出了什麼問題? 單元測試的目標是一次只驗證一個方法 小步的前進 細粒度的測試 但是假如某個方法依賴於其他一些難以操控的東東 比如說網路連接 資料庫連接 或者是Servlet容器 那麼我們該怎麼辦呢? 要是你的測試依賴於系統的其他部分 甚至是系統的多個其他部分呢?在這種情況下 倘若不小心 你最終可能會發現自己幾乎初始化了系統的每個組件 而這只是為了給一個測試創造足夠的慶攜芹運行環境讓它們可以運行起來 忙乎了大半天 看上去我們好像有點違背了測試的初衷了 這樣不僅僅消耗時間 還給測試過程引入了大量的耦合因素 比如說 可能有人興致沖沖地改變了一個介面或者資料庫的一張表 突然 你那卑微的單元測試的神秘的掛掉了 在這種情況發生幾次之後 即使是最有耐心的開發者也會泄氣 甚至最終放棄所有的測試 那樣的話後果就不能想像了 再讓我們看一個更加具體的情況 在實際的面向對象軟體設計中 我們經常會碰到這樣的情況 我們在對現實對象進行構建之後 對象之間是通過一系列的介面來實現 這在面向對象設計里是最自然不過的事情了 但是隨著軟體測試需求的發展 這會產生一些小問題 舉個例子 用戶A現在拿到一個用戶B提供的介面 他根據這個介面實現了自己的需求 但是用戶A編譯自己的代碼後 想簡單模擬測試一下 怎麼辦呢?這點也是很現實的一個問題 我們是否可以針對這個介面來簡單實現一個代理類 來測試模擬 期望代碼生成自己的結果呢? 幸運的是 有一種測試模式可以幫助我們 mock對象 Mock對象也就是真實對象在調試期的替代品

現在需要Mock對象嗎? 關於什麼時候需要Mock對象 Tim Mackinnon給我們了一些建議 譽畢 真實對象具有不可確定的行為(產生不可預測的結果 如股票的行情) 真實對象很難被創建(比如具體的web容器) 真實對象的某些行為很難觸發(比如網路錯誤) 真實情況令程序的運行速度很慢 真實對象有用戶界面 測試需要詢問真實對象它是如何被調用的(比如測試可能需要驗證某個回調函數是否被調用了) 真實對象實際上並不存在(當需要和其他開發小組 或者新的硬體系統打交道的時候 這是一個普遍的問題) 如何實現Mock對象? 使用mock對象進行測試的時候 我們總共需要 個步驟 分別是 使用一個介面來描述這個對象 為產品代碼實現這個介面 以測試為目的 在mock對象中實現這個介面 在此我們又一次看到了針對介面編程的重要性了 因為被測試的代碼只會通過介面來引用對象 所以它完全可以不知道它引用的究竟是真實的對象還是mock對象 下面看一個實際的例子 一個鬧鍾根據時間來進行提醒服務 如果過了下午 點鍾就播放音頻文件提醒大家下班了 如果我們要利用真實的對象來測試的話就只能苦苦等到下午五點 然後把耳朵放在音箱旁 我們可不想這么笨 我們應該利用mock對象來進行測試 這樣我們就可隱讓以模擬控制時間了 而不用苦苦等待時鍾轉到下午 點鍾了 下面是代碼

public interface Environmental { private boolean playedWav = false; public long getTime(); public void playWavFile(String fileName); public boolean wavWasPlayed(); public void resetWav(); }

真實的實現代碼

public class SystemEnvironment implements Environmental { public long getTime() { return System currentTimeMillis(); } public void playWavFile(String fileName) { playedWav = true; } public boolean wavWasPlayed() { return playedWav; } public void resetWav() { playedWav = false; } }

下面是mock對象

public class MockSystemEnvironment implements Environmental { private long currentTime; public long getTime() { return currentTime; } public void setTime(long currentTime) { this currentTime = currentTime; } public void playWavFile(String fileName) { playedWav = true; } public boolean wavWasPlayed() { return playedWav; } public void resetWav() { playedWav = false; } }

下面是一個調用getTime的具體類

import java util Calendar; public class Checker { private Environmental env; public Checker(Environmental env) { this env = env; } public void reminder() { Calendar cal = Calendar getInstance(); cal setTimeInMills(env getTime()); int hour = cal get(Calendar HOUR_OF_DAY); if(hour >= ) { env playWavFile( quit_whistle wav ); } } }

使用env getTime()的被測代碼並不知道測試環境和真實環境之間的區別 因為它們都實現了相同的介面 現在 你可以藉助mock對象 通過把時間設置為已知值 並檢查行為是否如預期那樣來編寫測試

import java util Calendar; import junit framework TestCase; public class TestChecker extends TestCase { public void testQuittingTime() { MockSystemEnvironment env = new MockSystemEnvironment(); Calendar cal = Calendar getInstance(); cal set(Calendar YEAR ); cal set(Calendar MONTH ); cal set(Calendar DAY_OF_MONTH ); cal set(Calendar HOUR_OF_DAY );

cal set(Calendar MINUTE ); long t = cal getTimeInMillis(); env setTime(t ); Checker checker = new Checker(env); checker reminder(); assertFalse(env wavWasPlayed()); t += ( * * ); env setTime(t ); checker reminder(); assertTrue(env wavWasPlayed()); env resetWav(); t += * * * ; env setTime(t ); checker reminder(); assertTrue(env wavWasPlayed()); } }

這就是mock對象的全部 偽裝出真實世界的某些行為 使你可以集中精力測試好自己的代碼

好像有一些麻煩 如果每次都像上面那樣自己寫具體的mock對象 問題雖然解決了 但是好像有一些麻煩 不要著急 已經有一些第三方現成的mock對象供我們使用了 使用Mock Object進行測試 主要是用來模擬那些在應用中不容易構造(如HttpServletRequest必須在Servlet容器中才能構造出來)或者比較復雜的對象(如JDBC中的ResultSet對象)從而使測試順利進行的工具 目前 在Java陣營中主要的Mock測試工具有JMock MockCreator Mockrunner EasyMock MockMaker等 在微軟的 Net陣營中主要是Nmock NetMock等 下面就以利用EasyMock模擬測試Servlet組件為例 代碼如下 編譯並將其當做一個Test Case運行 會發現兩個測試方法均測試成功 我們可以看到easymock已經幫助我們實現了一些servlet組件的mock對象 這樣我們就可以擺脫web容器和servlet容器來輕松的測試servlet了

import easymock *; import junit framework *; import javax servlet *; public class MockRequestTest extends TestCase{ private MockControl control; private HttpServletRequest mockRequest; public void testMockRequest(){ //創建一個Mock HttpServletRequest的MockControl對象 control = MockControl createControl(HttpServletRequest class); //獲取一個Mock HttpServletRequest對象 mockRequest = (HttpServletRequest) control getMock(); //設置期望調用的Mock HttpServletRequest對象的方法 mockRequest getParameter( name ); //設置調用方法期望的返回值 並指定調用次數 //以下後兩個參數表示最少調用一次 最多調用一次 control setReturnValue( kongxx ); //設置Mock HttpServletRequest的狀態 //表示此Mock HttpServletRequest對象可以被使用 control replay(); //使用斷言檢查調用 assertEquals( kongxx mockRequest getParameter( name )); //驗證期望的調用 control verify(); } }

編譯並將其當做一個Test Case運行 會發現兩個測試方法均測試成功 我們可以看到easymock已經幫助我們實現了一些servlet組件的mock對象 這樣我們就可以擺脫web容器和servlet容器來輕松的測試servlet了

底層技術是什麼? 讓我們來回憶一下 如果用戶使用C++和java的程序的生成 C++在最後的階段還需要連接才能生成一個整體程序 這在靈活性與java源代碼的機制是不能比的 java的各個類是獨立的 打包的那些類也是獨立的 只有在載入進去才進行連接 這在代碼被載入進去的時候 我們還可以執行很多的動作 如插入一些相關的業務需求 這也是AOP的一個焦點 javassit代碼庫的實現類似於這 正是利用這些 所以用java實現Mock對象是很簡單的

lishixin/Article/program/Java/JSP/201311/19222

❻ 就黑客歷史進行討論!~

黑客是對英語hacker的翻譯,hacker原意是指用斧頭砍材的工人,最早被引進計算機圈則可追溯自1960年代。他們破解系統或者網路基本上是一項業余嗜好,通常是出於自己的興趣,而非為了賺錢或工作需要。

加州柏克萊大學計算機教授Brian Harvey在考證此字時曾寫到,當時在麻省理工學院中(MIT)的學生通常分成兩派,一是tool,意指乖乖牌學生,成績都拿甲等;另一則是所謂的hacker,也就是常逃課,上課愛睡覺,但晚上卻又精力充沛喜歡搞課外活動的學生。 這跟計算機有什麼關系?一開始並沒有。不過當時hacker也有區分等級,就如同tool用成績比高下一樣。真正一流hacker並非整天不學無術,而是會熱衷追求某種特殊嗜好,比如研究電話、鐵道(模型或者真的)、科幻小說,無線電,或者是計算機。也因此後來才有所謂的computer hacker出現,意指計算機高手。

有些人很強調黑客和駭客的區別,根據開放原始碼計劃創始人Eric Raymond(他本人也是個著名的hacker)對此字的解釋,hacker與cracker(一般譯為駭客,有時也叫「黑帽黑客」。 )是分屬兩個不同世界的族群,基本差異在於,黑客是有建設性的,而駭客則專門搞破壞。 對一個黑客來說,學會入侵和破解是必要的,但最主要的還是編程,畢竟,使用工具是體現別人的思路,而程序是自己的想法.一句話--編程實現一切。對於一個駭客來說,他們只追求入侵的快感,不在乎技術,他們不會編程,不知道入侵的具體細節。還有一種情況是試圖破解某系統或網路以提醒該系統所有者的系統安全漏洞,這群人往往被稱做「白帽黑客」或「匿名客」(sneaker)或紅客。許多這樣的人是電腦安全公司的雇員,並在完全拆碼陵合法的情況下攻擊某系統。

黑客守則
1. 不惡意破壞任何的系統, 這樣作只會給你帶來麻煩。惡意破壞它模吵人的軟體將導致法律責任, 如果你只是使用電腦, 那僅為非法使用。 注意:千萬不要破壞別人的文件或數據。
2. 不修改任何系統文件, 如果你是為了要進入系統而修改它, 請在達到目的後將它還原。
3. 不要輕易的將你要 Hack 的站點告訴你不信任的朋友。
4. 不要在 bbs/論壇上談論關於你 Hack 的任何事情。
5. 在 Post 文章的時候不要使用真名。
6. 入侵期間, 不要隨意離開你的電腦。
7. 不要入侵或攻擊電信/政府機關的主機。
8. 不在電話中談論關於你 Hack 的任何事情。
9. 將你的筆記放在安全的地方。
10.讀遍所有有關系統安全或系統漏洞的文件 (英文快點學好)!
11.已侵入電腦中的帳號不得刪除或修改。
12.不得修改系統文件, 如果為了隱藏自己的侵入而作的修改則不在此限, 但仍須維持原來系統的安全性, 不得因得到系統的控制權而破壞原有的安全性。
13.不將你已破解的帳號分享與你的朋友。
14.不要侵入或破壞政府機關的主機。

但到了今天,在知識貧乏的記者寫的媒報道中,黑客一詞已被用於泛指黑客和駭客,因此也影響了大眾對黑客的理解。 這個背景下,就出現了重新定義黑客內涵的努力,試圖把黑客的活動范圍限定為不為經濟利益、而是出於好奇心做出技術探索和挑戰。

黑客文化簡史
本篇原作者為Eric S. Raymond [email protected],他是一位大哥級的 Hacker,寫了很多自由軟體,知名著作有Jargon File等,近年來發表「大教堂與集市」論文為Opensource software努力,Netscape 願意公開Navigator的原始碼,與這篇文章有很旅戚大的關系。

序曲: Real Programmer
故事一開始,我要介紹的是所謂的Real Programmer。
他們從不自稱是Real Programmer、Hacker或任何特殊的稱號;`Real Programmer' 這個名詞是在1980年代才出現,但早自1945年起,電腦科學便不斷地吸引世界上頭腦最頂尖、想像力最豐富的人投入其中。從Eckert &Mauchly發明ENIAC後,便不斷有狂熱的programmer投入其中,他們以撰寫軟體與玩弄各種程式設計技巧為樂,逐漸形成具有自我意識的一套科技文化。當時這批Real Programmers主要來自工程界與物理界,他們戴著厚厚的眼鏡, 穿聚酯纖維T恤與純白襪子,用機器語言、匯編語言、FORTRAN及很多古老的 語言寫程式。他們是Hacker時代的先驅者,默默貢獻,卻鮮為人知。
從二次大戰結束後到1970早期,是打卡計算機與所謂"大鐵塊"的mainframes 流行的年代,由Real Programmer主宰電腦文化。Hacker傳奇故事如有名的 Mel (收錄在Jargon File中)、Murphy's Law的各種版本、mock- German`Blinke_nlight' 文章都是流傳久遠的老掉牙笑話了。
※譯者:Jargon File亦是本文原作者所編寫的,裡面收錄了很多Hacker用語、縮寫意義、傳奇故事等等。Jargon File有出版成一本書:The New Hacker's Dictionary,MIT PRESS出版。也有Online版本: http://www.ccil.org/jargon
※譯者:莫非定律是:當有兩條路讓你抉擇,若其中一條會導致失敗,你一定會選到它。 它有很多衍生說法: 比如一個程式在demo前測試幾千幾萬次都正確無誤,但demo 那一天偏偏就會出bug。
一些Real Programmer仍在世且十分活躍 (本文寫在1996年)。超級電腦Cray 的設計者Seymour Cray, 據說親手設計Cray全部的硬體與其操作系統,作業系統是他用機器碼硬幹出來的,沒有出過任何bug或error。Real Programmer 真是超強!
舉個比較不那麼誇張的例子:Stan Kelly-Bootle,The Devil's DP Dictionary 一書的作者(McGraw-Hill, 1981年初版,ISBN 0-07-034022-6)與Hacker 傳奇專家,當年在一台Manchester Mark I開發程式。 他現在是電腦雜志的專欄作家,寫一些科學幽默小品,文筆生動有趣投今日hackers所好,所以很受歡迎。 其他人像David E. Lundstorm,寫了許多關於Real Programmer的小故事,收錄在A few Good Men From UNIVAC這本書,1987年出版,ISBN-0- 262-62075-8。
※譯:看到這里,大家應該能了解,所謂Real Programmer指的就是用組合語 言或甚至機器碼,把程式用打卡機punch出一片片紙卡片,由主機讀卡機輸入電腦的那種石器時代Programmer。
Real Programmer的時代步入尾聲,取而代之的是逐漸盛行的Interactive computing,大學成立電算相關科系及電腦網路。它們催生了另一個持續的工程傳統,並最終演化為今天的開放代碼黑客文化。
早期的黑客
Hacker時代的濫觴始於1961年MIT出現第一台電腦DEC PDP-1。MIT的Tech Model Railroad Club(簡稱TMRC)的Power and Signals Group買了這台機器後,把它當成最時髦的科技玩具,各種程式工具與電腦術語開始出現,整個環境與文化一直發展下去至今日。 這在Steven Levy的書`Hackers' 前段有詳細的記載(Anchor/Doubleday 公司,1984年出版,ISBN 0-385-19195-2)。
※譯:Interactive computing並非指Windows、GUI、WYSIWYG等介面, 當時有terminal、有shell可以下指令就算是Interactive computing了。 最先使用Hacker這個字應該是MIT。1980年代早期學術界人工智慧的權威:MIT 的Artificial Intelligence Laboratory,其核心人物皆來自TMRC。從1969年起,正好是ARPANET建置的第一年,這群人在電腦科學界便不斷有重大突破與貢獻。
ARPANET是第一個橫跨美國的高速網路。由美國國防部所出資興建,一個實驗性 質的數位通訊網路,逐漸成長成聯系各大學、國防部承包商及研究機構的大網路。各地研究人員能以史無前例的速度與彈性交流資訊,超高效率的合作模式導致科技的突飛猛進。
ARPANET另一項好處是,資訊高速公路使得全世界的hackers能聚在一起,不再像以前孤立在各地形成一股股的短命文化,網路把他們匯流成一股強大力量。 開始有人感受到Hacker文化的存在,動手整理術語放上網路, 在網上發表諷刺文學與討論Hacker所應有的道德規范。(Jargon File的第一版出現在1973年,就是一個好例子), Hacker文化在有接上ARPANET的各大學間快速發展,特別是(但不全是)在信息相關科系。
一開始,整個Hacker文化的發展以MIT的AI Lab為中心,但Stanford University 的Artificial Intelligence Laboratory(簡稱SAIL)與稍後的Carnegie-Mellon University(簡稱CMU)正快速崛起中。三個都是大型的資訊科學研究中心及人工智慧的權威,聚集著世界各地的精英,不論在技術上或精神層次上,對Hacker文化都有極高的貢獻。
為能了解後來的故事,我們得先看看電腦本身的變化;隨著科技的進步,主角MIT AI Lab也從紅極一時到最後淡出舞台。
從MIT那台PDP-1開始,Hacker們主要程式開發平台都是Digital Equipment Corporation 的PDP迷你電腦序列。DEC率先發展出商業用途為主的interactive computing及time-sharing操作系統,當時許多的大學都是買DEC的機器, 因為它兼具彈性與速度,還很便宜(相對於較快的大型電腦mainframe)。 便宜的分時系統是Hacker文化能快速成長因素之一,在PDP流行的時代, ARPANET上是DEC機器的天下,其中最重要的便屬PDP-10,PDP-10受到Hacker們的青睞達十五年;TOPS-10(DEC的操作系統)與MACRO-10(它的組譯器),許多懷舊的術語及Hacker傳奇中仍常出現這兩個字。
MIT像大家一樣用PDP-10,但他們不屑用DEC的操作系統。他們偏要自己寫一個:傳說中赫赫有名的ITS。
ITS全名是`Incompatible Timesharing System',取這個怪名果然符合MIT的搞怪作風——就是要與眾不同,他們很臭屁但夠本事自己去寫一套操作系統。ITS始終不穩,設計古怪,bug也不少,但仍有許多獨到的創見,似乎還是分時系統中開機時間最久的紀錄保持者。
ITS本身是用匯編語言寫的,其他部分由LISP寫成。LISP在當時是一個威力強大與極具彈性的程式語言;事實上,二十五年後的今天,它的設計仍優於目前大多數的程式語言。LISP讓ITS的Hacker得以盡情發揮想像力與搞怪能力。LISP是MIT AI Lab成功的最大功臣,現在它仍是Hacker們的最愛之一。
很多ITS的產物到現在仍活著;EMACS大概是最有名的一個,而ITS的稗官野史仍為今日的Hacker們所津津樂道,就如同你在Jargon File中所讀到的一般。在MIT紅得發紫之際,SAIL與CMU也沒閑著。SAIL的中堅份子後來成為PC界或圖形使用者介面研發的要角。CMU的Hacker則開發出第一個實用的大型專家系統與工業用機器人。
另一個Hacker重鎮是XEROX PARC公司的Palo Alto Research Center。從1970初期到1980中期這十幾年間,PARC不斷出現驚人的突破與發明,不論質或量,軟體或硬體方面。如現今的視窗滑鼠介面,雷射印表機與區域網路;其D系列的機器,催生了能與迷你電腦一較長短的強力個人電腦。不幸這群先知先覺者並不受到公司高層的賞識;PARC是家專門提供好點子幫別人賺錢的公司成為眾所皆知的大笑話。即使如此,PARC這群人對Hacker文化仍有不可抹滅的貢獻。1970年代與PDP-10文化迅速成長茁壯。Mailing list的出現使世界各地的人得以組成許多SIG(Special-interest group),不只在電腦方面,也有社會與娛樂方面的。DARPA對這些非`正當性'活動睜一隻眼閉一隻眼, 因為靠這些活動會吸引更多的聰明小夥子們投入電腦領域呢。
有名的非電腦技術相關的ARPANET mailing list首推科幻小說迷的,時至今日ARPANET變成Internet,愈來愈多的讀者參與討論。Mailing list逐漸成為一種公眾討論的媒介,導致許多商業化上網服務如CompuServe、Genie與Prodigy的成立。
Unix的興起
此時在新澤西州的郊外,另一股神秘力量積極入侵Hacker社會,終於席捲整個PDP-10的傳統。它誕生在1969年,也就是ARPANET成立的那一年,有個在AT&T Bell Labs的年輕小夥子Ken Thompson發明了Unix。
Thomspon曾經參與Multics的開發,Multics是源自ITS的操作系統,用來實做當時一些較新的OS理論,如把操作系統較復雜的內部結構隱藏起來,提供一個介面,使的programmer能不用深入了解操作系統與硬體設備,也能快速開發程式。
※譯:那時的programmer寫個程式必須徹底了解操作系統內部,或硬體設備。比方說寫有IO的程式,對於硬碟的轉速,磁軌與磁頭數量等等都要搞的一清二楚才行。
在發現繼續開發Multics是做白工時,Bell Labs很快的退出了(後來有一家公司Honeywell出售Multics,賠的很慘)。
Ken Thompson很喜歡Multics上的作業環境,於是他在實驗室里一台報廢的DEC PDP-7上胡亂寫了一個操作系統, 該系
統在設計上有從Multics抄來的也有他自己的構想。他將這個操作系統命名Unix,用來反諷Multics。
※譯:其實是Ken Thompson寫了一個游戲`Star Travel' 沒地方跑,就去找一台的報廢機器PDP-7來玩。他同事Brian Kernighan嘲笑Ken Thompson說:「你寫的系統好遜哦,乾脆叫Unics算了。」(Unics發音與太監的英文eunuches一樣),後來才改為Unix。
他的同事Dennis Ritchie,發明了一個新的程式語言C,於是他與Thompson用C把原來用匯編語言寫的Unix重寫一遍。C的設計原則就是好用,自由與彈性,C與Unix很快地在Bell Labs得到歡迎。1971年Thompson與Ritchie爭取到一個辦公室自動化系統的專案,Unix開始在Bell Labs中流行。不過Thompson與Ritchie的雄心壯志還不止於此。
那時的傳統是,一個操作系統必須完全用匯編語言寫成,始能讓機器發揮最高的效能。Thompson與Ritchie,是頭幾位領悟硬體與編譯器的技術,已經進步到作業系統可以完全用高階語言如C來寫,仍保有不錯的效能。五年後,Unix已經成功地移植到數種機器上。
※譯:Ken Thompson與Dennis Ritchie是唯一兩位獲得Turing Award(電腦界的諾貝爾獎)的工程師(其他都是學者)。
這當時是一件不可思議的事!它意味著,如果Unix可以在各種平台上跑的話,Unix 軟體就能移植到各種機器上。再也用不著為特定的機器寫軟體了,能在Unix上跑最重要,重新發明輪子已經成為過去式了。
除了跨平台的優點外,Unix與C還有許多顯著的優勢。Unix與C的設計哲學是Keep It Simple, Stupid'。programmer可以輕易掌握整個C的邏輯結構(不像其他之前或以後的程式語言)而不用一天到晚翻手冊寫程式。而Unix提供許多有用的小工具程式,經過適當的組合(寫成Shell script或Perl script),可以發揮強大的威力。
※註:The C Programming Language是所有程式語言書最薄的一本,只有兩百多頁哦。作者是Brian Kernighan 與Dennis Ritchie,所以這本C語言的聖經又稱`K&R'。
※註:`Keep It Simple, Stupid' 簡稱KISS,今日Unix已不follow這個原則,幾乎所有Unix 都是要灌一堆有的沒的utilities,唯一例外是MINIX。
C與Unix的應用范圍之廣,出乎原設計者之意料,很多領域的研究要用到電腦時,他們是最佳拍檔。盡管缺乏一個正式支援的機構,它們仍在AT&T內部中瘋狂的散播。到了1980年,已蔓延到大學與研究機構,還有數以千計的hacker想把Unix裝在家裡的機器上。
當時跑Unix的主力機器是PDP-11、VAX系列的機器。不過由於UNIX的高移植性,它幾乎可安裝在所有的電腦機型上。一旦新型機器上的UNIX安裝好,把軟體的C原始碼抓來重新編譯就一切OK了,誰還要用匯編語言來開發軟體?有一套專為UNIX設計的網路——UUCP:一種低速、不穩但成本很低廉的網路。兩台UNIX機器用條電話線連起來,就可以使用互傳電子郵件。UUCP是內建在UNIX系統中的,不用另外安裝。於是UNIX站台連成了專屬的一套網路,形成其Hacker文化。在1980第一個USENET站台成立之後,組成了一個特大號的分散式布告欄系統,吸引而來的人數很快地超過了ARPANET。
少數UNIX站台有連上ARPANET。PDP-10與UNIX的Hacker文化開始交流,不過一開始不怎麼愉快就是了。PDP-10的Hacker們覺得UNIX的擁護者都是些什麼也不懂的新手,比起他們那復雜華麗,令人愛不釋手的LISP與ITS,C與UNIX簡直原始的令人好笑。『一群穿獸皮拿石斧的野蠻人』他們咕噥著。
在這當時,又有另一股新潮流風行起來。第一部PC出現在1975年;蘋果電腦在1977年成立,以飛快的速度成長。微電腦的潛力,立刻吸引了另一批年輕的 Hackers。他們最愛的程式語言是BASIC,由於它過於簡陋,PDP-10 的死忠派與UNIX迷們根本不屑用它,更看不起使用它的人。
※譯:這群Hacker中有一位大家一定認識,他的名字叫Bill Gates,最初就是他在8080上發展BASIC compiler的。
古老時代的終結
1980年同時有三個Hacker文化在發展,盡管彼此偶有接觸與交流,但還是各玩各的。ARPANET/PDP-10文化,玩的是LISP、MACRO、TOPS-10與ITS。UNIX與C的擁護者用電話線把他們的PDP-11與VAX機器串起來玩。還有另一群散亂無秩序的微電腦迷,致力於將電腦科技平民化。
三者中ITS文化(也就是以MIT AI LAB為中心的Hacker文化)可說在此時達到全盛時期,但烏雲逐漸籠罩這個實驗室。ITS賴以維生的PDP-10逐漸過時,開始有人離開實驗室去外面開公司,將人工智慧的科技商業化。MIT AI Lab 的高手擋不住新公司的高薪挖角而紛紛出走,SAIL與CMU也遭遇到同樣的問題。
※譯:這個情況在GNU宣言中有詳細的描述,請參閱:(特別感謝由AKA的chuhaibo翻成中文)http://www.aka.citf.net/Magazine/Gnu/manifesto.html
致命一擊終於來臨,1983年DEC宣布:為了要集中在PDP-11與VAX生產線,將停止生產PDP-10;ITS沒搞頭了,因為它無法移植到其他機器上,或說根本沒人辦的到。而Berkeley Univeristy修改過的UNIX在新型的VAX跑得很順,是ITS理想的取代品。有遠見的人都看得出,在快速成長的微電腦科技下,Unix一統江湖是遲早的事。
差不多在此時Steven Levy完成``Hackers'' 這本書,主要的資料來源是Richard M. Stallman(RMS)的故事,他是MIT AI Lab領袖人物,堅決反對實驗室的研究成果商業化。
Stallman接著創辦了Free Software Foundation,全力投入寫出高品質的自由軟體。Levy以哀悼的筆調描述他是the last true hacker',還好事實證明Levy完全錯了。
※譯:Richard M. Stallman的相關事跡請參考: http://www.aka.citf.net/Magazine/Gnu/cover.htm
Stallman的宏大計劃可說是80年代早期Hacker文化的縮影——在1982年他開始建構一個與UNIX 相容但全新的操作系統,以C來寫並完全免費。整個ITS的精神與傳統,經由RMS的努力,被整合在一個新的,UNIX與VAX機器上的Hacker文化。微電腦與區域網路的科技,開始對Hacker文化產生影響。Motorola 68000 CPU 加Ethernet是個有力的組合,也有幾家公司相繼成立生產第一代的工作站。1982年,一群Berkeley出來的UNIX Hacker成立了Sun Microsystems,他們的算盤打的是:把UNIX架在以68000為CPU的機器,物美價廉又符合多數應用程式的要求。他們的高瞻遠囑為整個工業界樹立了新的里程碑。雖然對個人而言,工作站仍太昂貴,不過在公司與學校眼中,工作站真是比迷你電腦便宜太多了。在這些機構里,工作站(幾乎是一人一台)很快地取代了老舊龐大的VAX等timesharing機器。
※譯:Sun一開始生產的工作站CPU是用Motorola 68000系列,到1989才推出自行研發的以SPARC系列為CPU的SPARCstation。
私有Unix時代
1984年AT&T解散了,UNIX正式成為一個商品。當時的Hacker文化分成兩大類,一類集中在Internet與USENET上(主要是跑UNIX的迷你電腦或工作站連上網路),以及另一類PC迷,他們絕大多數沒有連上Internet。
※譯:台灣在1992年左右連上Internet前,玩家們主要以電話撥接BBS交換資訊,但是有區域性的限制,發展性也大不如USENET。Sun與其他廠商製造的工作站為Hacker們開啟了另一個美麗新世界。工作站訴求的是高效能的繪圖與網路,1980年代Hacker們致力為工作站撰寫軟體,不斷挑戰及突破以求將這些功能發揮到百分之一百零一。Berkeley發展出一套內建支援ARPANET protocols的UNIX,讓UNIX能輕松連上網路,Internet也成長的更加迅速。
除了Berkeley讓UNIX網路功能大幅提升外,嘗試為工作站開發一套圖形界面也不少。最有名的要算MIT開發的Xwindow了。Xwindow成功的關鍵在完全公開原始碼,展現出Hacker一貫作風,並散播到Internet上。X 成功的幹掉其他商業化的圖形界面的例子,對數年後UNIX的發展有著深遠的啟發與影響。少數ITS死忠派仍在頑抗著,到1990年最後一台ITS也永遠關機長眠了;那些死忠派在窮途末路下只有悻悻地投向UNIX的懷抱。
UNIX們此時也分裂為BerkeleyUNIX與AT&T兩大陣營,也許你看過一些當時的海報,上面畫著一台鈦翼戰機全速飛離一個爆炸中、上面印著AT&T的商標的死星。Berkeley UNIX的擁護者自喻為冷酷無情的公司帝國的反抗軍。就銷售量來說,AT&TUNIX始終趕不上BSD/Sun,但它贏了標准制訂的戰爭。到1990年,AT&T與BSD版本已難明顯區分,因為彼此都有採用對方的新發明。隨著90年代的來到,工作站的地位逐漸受到新型廉價的高檔PC的威脅,他們主要是用Intel80386系列CPU。第一次Hacker能買一台威力等同於十年前的迷你電腦的機器,上面跑著一個完整的UNIX,且能輕易的連上網路。沉浸在MSDOS世界的井底蛙對這些巨變仍一無所知,從早期只有少數人對微電腦有興趣,到此時玩DOS與Mac的人數已超過所謂的"網路民族"的文化,但他們始終沒成什麼氣候或搞出什麼飛機,雖然聊有佳作光芒乍現,卻沒有穩定發展出統一的文化傳統,術語字典,傳奇故事與神話般的歷史。它們沒有真正的網路,只能聚在小型的BBS 站或一些失敗的網路如FIDONET。提供上網服務的公司如CompuServe或Genie生意日益興隆,事實顯示non-UNIX的操作系統因為並沒有內附如compiler等程式發展工具,很少有source 在網路上流傳,也因此無法形成合作開發軟體的風氣。Hacker文化的主力,是散布在Internet各地,幾乎可說是玩UNIX的文化。他們玩電腦才不在乎什麼售後服務之類,他們要的是更好的工具、更多的上網時間、還有一台便宜32-bitPC。
機器有了,可以上網了,但軟體去哪找?商業的UNIX貴的要命,一套要好幾千大洋($)。90年代早期,開始有公司將AT&T與BSDUNIX移植到PC上出售。成功與否不論,價格並沒有降下來,更要緊的是沒有附原始碼,你根本不能也不準修改它,以符合自己的需要或拿去分享給別人。傳統的商業軟體並沒有給Hacker們真正想要的。
即使是FreeSoftwareFoundation(FSF)也沒有寫出Hacker想要的操作系統,RMS承諾的GNU操作系統——HURD 說了好久了,到1996年都沒看到影子(雖然1990年開始,FSF的軟體已經可以在所有的UNIX平台執行)。
早期的免費Unix
在這空窗期中,1992年一位芬蘭HelsinkiUniversity的學生--LinusTorvalds開始在一台386PC上發展一個自由軟體的UNIX kernel,使用FSF的程式開發工具。
他很快的寫好簡單的版本,丟到網路上分享給大家,吸引了非常多的Hacker來幫忙一起發展Linux-一個功能完整的UNIX,完全免費且附上全部的原始碼。Linux最大的特色,不是功能上的先進而是全新的軟體開發模式。直到Linux的成功前,人人都認為像操作系統這么復雜的軟體,非得要靠一個開發團隊密切合作,互相協調與分工才有可能寫的出來。商業軟體公司與80年代的FreeSoftwareFoundation所採用都是這種發展模式。
Linux則迥異於前者。一開始它就是一大群Hacker在網路上一起塗塗抹抹出來的。沒有嚴格品質控制與高層決策發展方針,靠的是每周發表新版供大家下載測試,測試者再把bug與patch貼到網路上改進下一版。一種全新的物競天擇、去蕪存菁的快速發展模式。令大夥傻眼的是,東修西改出來的Linux,跑的順極了。
1993年底,Linux發展趨於成熟穩定,能與商業的UNIX一分高下,漸漸有商業應用軟體移植到Linux上。不過小型UNIX廠商也因為Linux的出現而關門大吉——因為再沒有人要買他們的東西。倖存者都是靠提供BSD為基礎的UNIX 的完整原始碼,有Hacker加入發展才能繼續生存。
Hacker文化,一次次被人預測即將毀滅,卻在商業軟體充斥的世界中,披荊斬棘,篳路藍縷,開創出另一番自己的天地。
網路大爆炸時代
Linux能快速成長的來自令一個事實:Internet大受歡迎,90年代早期ISP如雨後春筍般的冒出來,World-Wide-Web的出現,使得Internet成長的速度,快到有令人窒息的感覺。
BSD專案在1994正式宣布結束,Hacker們用的主要是免費的UNIX(Linux與一些4.4BSD的衍生版本)。而LinuxCD-ROM銷路非常好(好到像賣煎餅般)。近幾年來Hacker們主要活躍在Linux與Internet發展上。World-Wide-Web讓Internet成為世界最大的傳輸媒體,很多80年代與90年代早期的Hacker們現在都在經營ISP。
Internet的盛行,Hacker文化受到重視並發揮其政治影響力。94、95年美國政府打算把一些較安全、難解的編碼學加以監控,不容許外流與使用。這個稱為Clipper proposal的專案引起了Hacker們的群起反對與強烈抗議而半途夭折。96年Hacker又發起了另一項抗議運動對付那取名不當的"Communications DecencyAct",誓言維護Internet上的言論自由。
電腦與Internet在21世紀將是大家不可或缺的生活用品,現代孩子在使用Internet科技遲早會接觸到Hacker文化。它的故事傳奇與哲學,將吸引更多人投入。未來對Hacker們是充滿光明的。

❼ 什麼時候用fake mock

Fake應用到測試以及進行原型設計或者峰值模擬中;當我們並不希望真的調用生產環境下的代碼或者在測試中難於驗證真實代碼執行效果的時候,我們會用Mock來替代那些真實的對象。
如何寫Fake的方法:
1,在代碼中有依賴,比如代碼依賴ABC.cpp文件里的方法。這些方法還沒有實現,這是應該是拿到了這些包含了這些方法的定義的頭文件,ABC.h。
2,創建一個Fake程序,Fake_ABC.cpp和Fake_ABC.h.在Fake_ABC.h里includeABC.h.並定義新的行為Fake_action_1(),Fack_action_2().這些行為多數是用來幫助獲取Fakeobject的狀態。
3,實現ABC.h里定義的行為,和Fake_ABC.h定義的額外增加的輔助測試的行為。
4,構建TDD測試case,寫proctioncode。
Fake更像是Stub,是對被Fake,Stub的對象做簡單的返回值處理。多少情況是程序的依賴程序不ready。而Mock是為了驗證依賴對象和被測程序的交互。需要花更多的功夫去實現。有時候被Mock對象是硬體依賴的,被Mock對象的實現是存在的,只是不能放入off-target測試環境里。這時候就需要對該對象進行Mock。和上述方法一樣,只是需要保證被Mock對象的實現.c,.cpp文件不能在測試項目裡面。否則Mock的函數實現和真實代碼的函數實現就會重復導致編譯鏈接錯誤。

❽ 怎麼用mockito mock 單例

當被問到要實現一個單例模式時,很多人的第一反應是寫出如下的代碼,包括教科書上也是這樣教我們的。一二三四5陸漆吧9一0一一publicclassSingleton{;privateSingleton(){}(){if(instance==null){instance=newSingleton();}returninstance;}}這段代山激碼簡單明了,而且使用了懶載入模式,但是卻存在致命的問題。當有多個線程並行調用getInstance()的時候,就會創建多個實例。也就是說在多線程下不能正常工作。懶漢式,線程安全為了解決上面的問題,最簡單的方法是將整個getInstance()方法設為同步(synchronized)。一二三四5陸(){if(instance==null){instance=newSingleton();}returninstance;}雖然做到了線程安全,並且解決了多實例的問題,但是它並不高效。因為在任何時候只能有一個線程調用getInstance()方法。但是同步操作只需要在第一次調用時才被需要,即第一次創建單例實例對象時。這就引出了雙重檢驗鎖。雙重檢驗鎖雙重檢驗鎖模式(doublecheckedlockingpattern),是一種使用同步塊加鎖的方法。程序員稱其為雙重檢查鎖,因為會有兩次檢查instance==null,一次是在同步塊外,一次是在同步塊內。為什麼在同步塊內還要再檢驗一次?因為可能會有多個線程一起進入同步塊外的if,如果在同步塊內不進行二次檢驗的話就會生成多嫌唯敏個實例了。一二三四5陸漆吧9一(){if(instance==null){//SingleCheckedsynchronized(Singleton.class){if(instance==null){//DoubleCheckedinstance=newSingleton();}}}returninstance;}這段代碼看起來很完美,很可惜,它是有問題。主要在於instance=newSingleton()這句,這並非是一個原子操作,事實上在JVM中這句話大概做了下面三件事情。給instance分配內存調用Singleton的構造函數來初始化成員變數將instance對象指向分配的內存空間(執行完這步instance就為非null了)但是在JVM的即時編譯器中存在指令重排序的優化。也就是說上芹枝面的第二步和第三步的順序是不能保證的,最終的執行順序可能是一-二-三也可能是一-三-二。如果是後者,則在三執行完畢、二未執行之前,被線程二搶佔了,這時instance已經是非null了(但卻沒有初始化),所以線程二會直接返回instance,然後使用,然後順理成章地報錯。我們只需要將instance變數聲明成volatile就可以了。一二三四5陸漆吧9一0一一一二一三一四一5一陸publicclassSingleton{;//聲明成volatileprivateSingleton(){}(){if(instance==null){synchronized(Singleton.class){if(instance==null){instance=newSingleton();}}}returninstance;}}有些人認為使用volatile的原因是可見性,也就是可以保證線程在本地不會存有instance的副本,每次都是去主內存中讀取。但其實是不對的。使用volatile的主要原因是其另一個特性:禁止指令重排序優化。也就是說,在volatile變數的賦值操作後面會有一個內存屏障(生成的匯編代碼上),讀操作不會被重排序到內存屏障之前。比如上面的例子,取操作必須在執行完一-二-三之後或者一-三-二之後,不存在執行到一-三然後取到值的情況。從「先行發生原則」的角度理解的話,就是對於一個volatile變數的寫操作都先行發生於後面對這個變數的讀操作(這里的「後面」是時間上的先後順序)。但是特別注意在Java5以前的版本使用了volatile的雙檢鎖還是有問題的。其原因是Java5以前的JMM(Java內存模型)是存在缺陷的,即時將變數聲明成volatile也不能完全避免重排序,主要是volatile變數前後的代碼仍然存在重排序問題。這個volatile屏蔽重排序的問題在Java5中才得以修復,所以在這之後才可以放心使用volatile。相信你不會喜歡這種復雜又隱含問題的方式,當然我們有更好的實現線程安全的單例模式的法。餓漢式staticfinalfield這種方法非常簡單,因為單例的實例被聲明成static和final變數了,在第一次載入類到內存中時就會初始化,所以創建實例本身是線程安全的。一二三四5陸漆吧9一0publicclassSingleton{//類載入時就初始化=newSingleton();privateSingleton(){}(){returninstance;}}這種寫法如果完美的話,就沒必要在啰嗦那麼多雙檢鎖的問題了。缺點是它不是一種懶載入模式(lazyinitialization),單例會在載入類後一開始就被初始化,即使客戶端沒有調用getInstance()方法。餓漢式的創建方式在一些場景中將無法使用:譬如Singleton實例的創建是依賴參數或者配置文件的,在getInstance()之前必須調用某個方法設置參數給它,那樣這種單例寫法就無法使用了。靜態內部類staticnestedclass我比較傾向於使用靜態內部類的方法,這種方法也是《EffectiveJava》上所推薦的。一二三四5陸漆吧9publicclassSingleton{{=newSingleton();}privateSingleton(){}(){returnSingletonHolder.INSTANCE;}}這種寫法仍然使用JVM本身機制保證了線程安全問題;由於SingletonHolder是私有的,除了getInstance()之外沒有法訪問它,因此它是懶漢式的;同時讀取實例的時候不會進行同步,沒有性能缺陷;也不依賴JDK版本。枚舉Enum用枚舉寫單例實在太簡單了!這也是它最大的優點。下面這段代碼就是聲明枚舉實例的通常做法。一二三publicenumEasySingleton{INSTANCE;}我們可以通過EasySingleton.INSTANCE來訪問實例,這比調用getInstance()方法簡單多了。創建枚舉默認就是線程安全的,所以不需要擔心doublecheckedlocking,而且還能防止反序列化導致重新創建新的對象。但是還是很少看到有人這樣寫,可能是因為不太熟悉吧。總結一般來說,單例模式有五種寫法:懶漢、餓漢、雙重檢驗鎖、靜態內部類、枚舉。上述所說都是線程安全的實現,文章開頭給出的第一種方法不算正確的寫

❾ make的片語

1.make up to sb 討好、巴結某人
2.make up for sth in/with 彌補
3.make towards sth 移動,移向
4.make sth of sb/sth 了解、理解
5.make sb/sth into sth 將......製成(變成)
6.make out 聽出,看出,辨認出
7.make off 溜掉,匆忙離開
8.make off with sth 搶走,拿走(兄亮汪他人之物)
9.make for sth 朝......走去,朝......前進
10.make away with sb/sth 偷竊(某物)
11.make the most of 充分利用(同make the best of)
12.make use of sth. 利用某物
13.make a go of sth 盡力以使某事成功
14.make too much of 過分重視
15.make a day/night/evening of it 花整天/整夜/整個晚上的時間做某事
16.make out a cheque/bill etc 開支票/帳單等
17.make sb out to be sth 假稱,把......說成
18.make out a case (for) 找到充分的理由證明(解釋)
19.make sb. doing sth. 讓某人一直做某事
20.make sth. done 指讓別人幫助完成某事
21.make sb do sth 讓某人做某事
22.make sb be+adj.
23.make good use of/make full use of 充分利用
24.make ends meet 使收支相抵
25.make no sense 講不通,沒意義,不能被理解
26.make sense of 理解
27.make up打扮;編,創造
28.make for 有助於,有利於
29.make up of 由……組成
30.be made of/from 由……組成
31.be made in 在……生產
32.make it 成功
33.make sb. out理解,明白
34.make money賺錢 make
v.(動詞)
過去式:made [meid] 現在分詞:making['meɪkɪŋ],第三人稱單數makes [meiks]
(1)
To cause to exist or happen; bring about; create:
使存在,使發生:導致存在或發生;使發生;創造:
made problems for him; making a commotion.
為他製造問題;引發暴亂
(2)
To bring into existence by shaping, modifying, or putting together material; construct:
製成:用塑造、修改或把材料放在一塊的方法導致存在;建造:
make a dress; made a wall of stones.
做衣服;砌石牆
(3)
To form by assembling indivials or constituents:
集成:把個體或成份組合而形成:
make a quorum.
達到法定人數
(4)
To change from one form or function to another:
使功能改變:把一種形式或功能轉換成另外一種:
make clay into bricks.
把泥土製成磚塊
(5)
To cause to be or become:
使成或變成:
made her position clear; a decision that made him happy.
使鍵肢她的地位明朗化;此決定令他高興
(6)
To cause to assume a specified function or role:
當做,當成:使具有一種特定的功能或成為某個角色:
made her treasurer; made Chicago his home.
視她為出納員;把芝加羨仔哥當成他的家
(7)
To cause to act in a specified manner:
造成,導致:以特定的方式引起行動:
Heat makes gases expand.
熱使得氣體膨脹
(8)
To compel:
促使:
made him leave.
迫使他離開
(9)
To form in the mind:
在頭腦中形成:
make an estimate.
做估算
(10)
To compose:
創作:
make verses.
創作詩歌
(11)
To prepare; fix:
准備;安排:
make breakfast.
准備早餐
(12)
To get ready or set in order for use:
准備使用:准備或料理好以便使用:
made the bed.
整理床鋪
(13)
To gather and light the materials for (a fire).
生火:收集材料並點燃(生火)
(14)
To engage in:
從事:
make war.
開戰
(15)
To carry out; perform:
執行;進行:
make a telephone call; make an incision.
打電話;切開
(16)
To achieve, proce, or attain:
實現,產生,達到:
made peace between the two factions; not making sense; didn't make the quota.
在兩個派別之間實現和平;毫無意義;沒有達到定額
(17)
To institute or establish; enact:
制訂:制定或者建立;頒布:
make laws.
制定法律
(18)
To draw up and execute in a suitable form:
訂立:以合適的形式擬定並實施:
make a will.
立遺囑
(19)
To arrive at; reach:
到達;抵達:
made Washington in two hours.
在兩小時內到達華盛頓
(20)
To reach in time:
及時趕上:
just made the plane.
剛好趕上飛機
(21)
To attain the rank or position of:
達到地位:達到某種職位或軍銜:
She made lieutenant.
她的軍銜為中尉
(22)
To acquire a place in or on:
組成,得到:獲得一個位置:
made the basketball team; made the morning papers.
組成籃球隊;收到早報了
(23)
To gain or earn, as by working:
賺到:通過工作賺得或獲得:
make money.
賺錢
(24)
To behave so as to acquire:
使成為:為了獲取而做某些行為:
make friends.
交朋友
(25)
To score or achieve, as in a sport:
得分:在體育比賽中得分或成功:
made a field goal.
射門得分
(26)
To assure the success of:
確保…的成功:
A favorable review from him can make a play.
他贊賞的評論能使這場戲成功
(27)
To favor the development of:
有利於…的發展:
Practice makes a winning team.
勤加訓練必有助於球隊獲得勝利
(28)
To be suited for:
對…合適:
Oak makes strong furniture.
橡木合適做耐用傢具
(29)
To develop into:
發展成為:
She will make a fine doctor.
她將會成為一個好醫生
(30)
To draw a conclusion as to the significance or nature of:
下結論:作出對…的意義或本性的結論:
don't know what to make of the decision.
不知道怎樣作決定
(31)
To calculate as being; estimate:
估計是;估算:
I make the height 20 feet.
我估計有20英尺高
(32)
To consider as being:
認為是:
wasn't the problem some people made it.
有些人不認為這是一個問題
(33)
To constitute:
構成:
Twenty members make a quorum.
二十個成員構成法定人數
(34)
To add up to:
等於:
Two and two make four.
二加二等於四
(35)
To amount to:
接近,相當於:
makes no difference.
沒有什麼區別
(36)
To constitute the essence or nature of:
架構:構成…的精華或本質:
Clothes make the man.
由穿著便可了解一個人
(37)
To cause to be especially enjoyable or rewarding:
使有意義:使成為特別有樂趣或值得的:
You made my day.
你使我的生活特別有意義
(38)
To appear to begin (an action):
准備:看上去開始(一個動作):
She made to leave.
她准備離開
(1)
To act or behave in a specified manner:
做:明確地做或行為:
make merry; make free.
快樂地做;自由地做
(2)
To begin or appear to begin an action:
准備做:開始或看上去開始一個動作:
made as if to shake my hand.
好象要和我握手
(3)
To cause something to be as specified:
確認:使某事物變得明確:
make ready; make sure.
准備好;確認
(4)
To proceed in a certain direction:
按某一方向前進:
made for home; made after the thief.
回家;追趕小偷
(5)
Slang To pretend to be; imitate. Used withlike :
【俚語】 假扮;模仿。與like 連用:
made like a ballerina.
模仿芭蕾舞女演員
(6)
To undergo fabrication or manufacture:
生產:經編寫或生產成為:
This wool makes up into a warm shawl.
這種羊毛織成了很暖和的圍巾
(7)
To rise or accumulate:
上升或積聚:
The tide is making.
正在漲潮
n.(名詞)
(1)
The act or process of making; manufacturing.
製造:製作或生產的動作或過程;生產
(2)
The style or manner in which a thing is made:
製作樣式:生產某事物的風格或方式:
disliked the make of her coat.
不喜歡她衣服的樣式
(3)
The amount proced, especially the output of a factory.
生產量:生產的數量,特別是一座工廠的產量
(4)
A specific line of manufactured goods, identified by the manufacturer's name or the registered trademark:
牌子:產品特定的種類,以生產商的名字或者注冊的商標來識別:
a famous make of shirt.
名牌襯衫
(5)
The physical or moral nature of a person; character or disposition:
性格:一個人的身體或精神上的本質;性格或者性情:
found out what make of man he was.
得知他是一個什麼樣的人
(6)
Slang Identification of a person or thing, often from information in police records:
【俚語】 檔案:一個人或事物的身份,經常從警方記錄的信息中得出:
Did you get a make on the assailant?
你得知有關攻擊者的資料了嗎? make for
(1)
To have or cause to have a particular effect or result:
造成,促成:有或促使有某種特定的效果或者結果的:
small details that make for comfort.
令人舒適的小節
(2)
To help promote; further:
幫助提升;推進:
makes for better communication.
促進更好的交流
make off
To depart in haste; run away.
急忙離開;跑走
make out
(1)
To discern or see, especially with difficulty:
辨明:辨明或看清,特別是在有困難的情況下:
I could barely make out the traffic signs through the rain.
在雨中我幾乎看不清交通標志
(2)
To understand:
理解:
could not make out what she was saying.
不能理解她在說些什麼
(3)
To write out; draw up:
寫下來;列出:
made out the invoices.
開具發票
(4)
To fill in (a form, for example).
填寫(如表格)
(5)
Informal To imply or suggest:
【非正式用語】 暗示,建議:
You make me not to be a liar.
你暗示我不要說謊
(6)
Informal To try to establish or prove:
【非正式用語】 試圖建立或者證明:
He made out that he was innocent.
他試圖證明自己是無辜的
(7)
To get along in a given way; fare:
進展:在給定的道路上前進;進展:
made out well in business.
在生意上進展順利
(8)
Slang
【俚語】
(9)
To neck; pet.
相互親吻;撫愛
(10)
To have sexual intercourse.
發生性關系
make over
(1)
To redo; renovate.
改裝;革新
(2)
To change or transfer the ownership of, usually by means of a legal document:
轉讓:改變或者轉移所有權,通常是通過法律文件的方式:
made over the property to her son.
把財產轉到她兒子名下
make up
(1)
To put together; construct or compose:
整理;建立或捏造:
make up a prescription.
開一個葯方
(2)
To constitute; form:
構成;組成:
One hundred years make up a century.
一百年構成一個世紀
(3)
To alter one's appearance for a role on the stage, as with a costume and cosmetics.
化妝:為在舞台上的角色而改變某人的外表,例如用服裝或化妝品
(4)
To apply cosmetics.
用化妝品化妝
(5)
To devise as a fiction or falsehood; invent:
捏造,編造:杜撰小說或謊話;捏造:
made up an excuse.
編造借口
(6)
To make good (a deficit or lack):
彌補:彌補(赤字或不足):
made up the difference in the bill.
彌補了帳單上的差額
(7)
To compensate for:
補償:
make up the lost time.
補足失去的時間
(8)
To resolve a quarrel:
和好:平息一場爭吵:
kissed and made up.
親吻和好
(9)
To make ingratiating or fawning overtures. Used withto :
獻殷勤,巴結:提出獻殷勤或討好的建議。和to 連用:
made up to his friend's boss.
向他朋友的老闆獻殷勤
(10)
To take (an examination or a course) again or at a later time because of previous absence or failure.
補考,補課:因為以前缺席或不及格在一段時間後再考或再上課
(11)
To set in order:
整理,收拾:
make up a room.
把房間收拾好
(12)
Printing To select and arrange material for:
【印刷術】 排版,整版:
made up the front page.
為封面排版
make with 【俚語】
(1)
To bring into use:
使用:
a flirt making with the eyes.
用眼睛調情
(2)
To put forth; proce:
長出;製造:
always making with the jokes.
總是談笑風生 make a clean breast of
To confess fully.
坦白交待
make a face
To distort the features of the face; grimace.
改變臉部的容貌;扮鬼臉
make a go of
To achieve success in:
在…獲得成功:
have made a go of the business.
生意上獲得了成功
make away with
(1)
To carry off; steal.
處理;偷
(2)
To use up or consume.
用光或消費
(3)
To kill or destroy.
殺死或破壞
make believe
To pretend.
假裝
make bold
To venture:
冒險:
I will not make so bold as to criticize such a distinguished scholar.
我不會冒險去批評這么傑出的一位學者
make book【游戲】
To accept bets on a race, game, or contest.
在賽馬、比賽或競賽中接受賭注
make do
To manage to get along with the means available:
用手頭擁有的錢去勉強應付:
had to make do on less income.
不得不用較少的收入來應付
make ends meet
To manage so that one's means are sufficient for one's needs.
收支平衡:設法使某人的財產和花費相抵
make eyes
To ogle.
向…送秋波
make fun of
To mock; ridicule.
嘲笑;嘲諷
make good
(1)
To carry out successfully:
成功地實施:
He made good his escape.
他成功地逃脫了
(2)
To fulfill:
實現:
She made good her promise.
她實現了諾言
(3)
To make compensation for; make up for:
補償;彌補:
made good the loss.
彌補損失
(4)
To succeed:
成功:
made good as a writer.
成為一個成功的作家
make hay
To turn to one's advantage:
利用:使對某人有利:
The candidate's opponents made hay of the scandal.
候選人的競爭對手利用這次丑聞做了手腳
make it
(1)
Informal To be successful:
【非正式用語】 成功:
finally made it as an actor.
最後成了一名成功的演員
(2)
Slang To have sexual intercourse.
【俚語】 發生性關系
make light of
To treat as unimportant:
輕視;忽略:
He made light of his illness.
他忽視了自己的疾病
make love
(1)
To engage in amorous caressing.
做愛撫的動作
(2)
To engage in sexual intercourse.
發生性關系
make much of
To treat as of great importance.
重視對待
make no bones about
To be forthright and candid about; acknowledge freely:
對…坦白或直爽;公開承認:
They make no bones about their dislike for each other.
他們毫不隱瞞彼此間的厭惡
make off with
To snatch or steal:
奪走或偷走:
made off with the profits.
奪走了利潤
make sail【航海】
(1)
To begin a voyage.
開始航行
(2)
To set sail.
張帆
make the grade
To measure up to a given standard.
達到給定的標准
make the most of
To use to the greatest advantage.
最大限度地利用
make the scene【俚語】
(1)
To put in an appearance:
出現:
made the scene at the party.
出現在聚會上
(2)
To participate in a specified activity:
參與具體的活動:
made the drug scene.
參與毒品活動
make time
(1)
To move or travel fast, as in an attempt to compensate for lost time.
彌補時間:運動或走得更快以便彌補失去的時間
(2)
Slang To make progress toward attracting:
【俚語】 更加有吸引力:
He tried to make time with the new neighbor.
他試圖獲取新鄰居的好感
make tracks【俚語】
To move or leave in a hurry.
匆忙走開或離去
make up (one's) mind
To decide between alternatives; come to a definite decision or opinion.
作出選擇;作出決定或提出意見
make waves【俚語】
To cause a disturbance or controversy.
引起混亂或爭論
make way
(1)
To give room for passage; move aside.
讓路;走到一邊
(2)
To make progress.
取得進步
on the make【俚語】
(1)
Aggressively striving for financial or social improvement:
拚命追求經濟上或社會地位上的提高:
a young executive on the make.
追求進步的年輕經理
(2)
Eagerly seeking a sexual partner.
急切地追求伴侶 (1)
Middle English maken
中古英語maken
(2)
from Old English macian * see mag-
源自 古英語 macian *參見 mag- mak「able
adj.(形容詞) make
vi.
(1)
前進, 向...去(for)
They were making towards the river.
他們正向河邊走去。②開始(do sth.); 行動得(象...); 似乎要
He made to go.
他要走了。
She made to reply and then stopped.
她似乎要回答又止住了。
(2)
(潮汐等)漲起; 增加, 增高
The tide is making now.
此刻正在漲潮。
(3)
被處理; 被製造
Toys are making in the shop.
這個車間正在製造玩具。
(4)
[後接形容詞, 表示某種狀態、方式]
make sure
查明
make ready
准備好
make merry
尋歡作樂
(5)
(紙牌中)洗牌; (一張牌)吃掉旁人的牌
n.
(1)
製造(法); 構造; 樣式; (產生)來源
(2)
(礦井等某一時期的)產量
(3)
性情; 品質; 體格
(4)
【電】閉合
(5)
(紙牌中)(輪流)洗牌
a man of this make
這種性格的人
at make
在接通的位置上
Is this your ownmake?
這是你自己製造的嗎? double make
雙閉合
percent make
脈沖占空系數
quick make
快速閉合[接通]
short make
抄造量短缺
slow make
緩慢接通 make shape fashion construct manufacture
都含「做、「造、「做成或製造成某種東西的意思。
(1)
make 系常用詞, 指「任何生產、形成或組成, 如:
This machine is made in China .
這台機器是中國製造的。
(2)
shape 指「由塑造、鑄造、切割、敲打而形成, 如:
The child shaped clay into balls.
那小孩把泥捏成球。
(3)
fashion 指「用手、某些工具或原料做成具有一定形狀的東西, 但通常暗示發明者的才華, 如:
They discovered that they could shear sheep, take the wool, weave it and fashion the material into warm coats and suits,.
他們發現他們能夠剪羊毛、紡絨線、織成毛料, 然後把毛料做成暖和的衣服。
(4)
construct 指「按設計把許多部分組成一個整體, 如:
They constructed a big bridge.
他們建成了一座大橋。
(5)
manufacture 指「用機器生產或製造, 尤指「使用機器大規模生產與製造, 如:
We can manufacture high-precision machine tools.
我們能造精密機床。
Make、include-文件
C 源碼的開頭經常有一系列被包含的頭文件,例如stdio.h。有一些是系統級的頭文件,有一些是你正在寫的項目的頭文件:
#include <stdio.h>
#include foo.h
int main(....
要確定在你的 foo.h 被改變之後,這個文件也會被重新編譯,就要在你的 Makefile 這樣寫:
foo: foo.c foo.h
當你的項目變得越來越大,你自己的頭文件越來越多的時候,要追蹤所有這些頭文件和所有依賴它的文件會是一件痛苦的事情。如果你改變了其中一個頭文件,卻忘了重新編譯所有依賴它的源文件,結果會是很失望的。gcc 有一個選項可以分析你的源文件然後產生一個頭文件的列表和它的依賴關系: -MM。
如果你把下面的內容加到你的 Makefile 裡面:
depend:
gcc -E -MM *.c > .depend
然後運行 make depend,就會產生一個 .depend,裡麵包含了目標文件,C 文件和頭文件的列表:
foo.o: foo.c foo.h
如果你改變了 foo.h,下一次運行 make 的時候,所有依賴 foo.h 的文件就會被重新編譯。
每一次你增加一個頭文件的時候,別忘了運行一次 make depend。 現代英漢綜合大辭典
make
[meik]
vt.
(made[meid])
(1)
做, 製造, 造成; 創造, 起草, 制定, 設置, 徵收, 准備
make a coat
製做上衣
make cloth
織布
make enemies
樹敵
make a self criticism
作自我批評
Don't make noise.
不要喧嘩。
You make too much fuss about trifles.
你太小題大做了。
(2)
布置, 整理, 訓練
make a fire
生火
make the bed
鋪床
make tea
泡茶
Make hay while the sun shines.
[諺]趁晴曬草,勿失良機。
(3)
構成, 組成
Oxygen and hydrogen make water.
氧和氫組成水。
One tree does not make a wood.
獨木不成林。
(4)
迫使; 促使
Can you make the horse go?
你能趕走這匹馬嗎?
His father wants to make him a doctor [to make a doctor of him].
他父親想讓他作一個醫生。
He soon made himself understood.
他立刻把自已的意思講明白了。
(5)
成為, 變成
If you work hard, you will make a good athlete.
如果你肯努力, 你將成為一個好運動員。
(6)
得; 賺, 掙
make a reputation
博得名聲
The picture makes a good price.
這張畫可賣個好價錢。
She made good marks at school.
她在學校的成績很好。
(7)
實行, 進行
make social investigation
進行社會調查
make war
開戰
(8)
等於; 相等
Twelve inches make one foot.
十二英寸等於一英尺。
(9)
猜想; 計算, 認為
What do you make the time?
你看(此時)幾點鍾了?
He is not an ass [a goose] as they make him.
他不象大家猜想的那樣笨。
(10)
到達; 抵
We made the airport in an hour.
不到一小時我們就到了機場。
(11)
走; 行進; [俚]趕上
The train makes 70 kilometres an hour.
這火車的時速為70公里。
I don't think he will make the morning train.
我看他趕不上早班火車。
(12)
【電】(電流)接通
(13)
實行; 簽訂, 締結
make a bow
鞠躬
make a contract
定契約
(14)
發表, 說, 提出
make a speech
[美]演說
(15)
發生; 使發生; 成為...的原因
(16)

make a good dinner [meal]
美餐一頓
(17)
行動得象...
make a fool of oneself
丟丑; 使自已成為笑柄
(18)
成為; 成為...會員, 在...里得到一地位
He made the college basket-ball team.
他成為大學籃球隊隊員。
(19)
【航海】開始看見
We made a cruiser in the distance.
我們看見遠處有一艘巡洋艦。⑵⑽(紙牌中)洗(牌); 打滿(叫牌數); 出(牌)勝一圈; 勝(一圈) ⑵
(20)
[俚]使與之性交, 引誘。

php打樁是什麼意思

PHP打樁演算法

打樁是一種用定製的函數替換鏈接庫函數且不需重新編譯的技術。甚至可用此技術替換系統調用(更確切地說,庫函數包裝系統調用)。可能的應用是沙盒、調試或性能優化庫。為演示過程,此處給出一個簡單庫,以記錄GNU/Linux中
malloc 調用次數。

/*_GNU_SOURCEisneededforRTLD_NEXT,GCCwillnotdefineitbydefault*/
#define_GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>
#include<stdint.h>
#include<inttypes.h>

staticuint32_tmalloc_count=0;
staticuint64_ttotal=0;

voidsummary(){
fprintf(stderr,"malloccalled:%utimes ",count);
fprintf(stderr,"totalallocatedmemory:%"PRIu64"bytes ",total);
}

void*malloc(size_tsize){
staticvoid*(*real_malloc)(size_t)=NULL;
void*ptr=0;

if(real_malloc==NULL){
real_malloc=dlsym(RTLD_NEXT,"malloc");
atexit(summary);
}

count++;
total+=size;

returnreal_malloc(size);
}

打樁祥皮要在鏈接libc.so之前載入此庫,這樣我們的 malloc 實現就會在二進制文件執行時被鏈接。可通過設置 LD_PRELOAD
環境變數為我們想讓鏈接器優先鏈接的全路徑。這也能確保其他動態鏈接庫的調用最終使用我們的 malloc
實現。因為我們的目標只是記錄調用次數,不是真正地實現內存分配,所以我們仍需要調用「真正」的 malloc 。通過傳遞 RTLD_NEXT 偽處理程序到
dlsym,我們獲得了指向下一個已載入的鏈接庫中 malloc 事件的指針。第一次 malloc 調用 libc 的 malloc,當程序終止時,會調用由
atexit 注冊的獲取和 summary 函數。看GNU/Linxu中打樁行為(真的184次調用!):

$gcc-shared-ldl-fPICmalloc_counter.c-o/tmp/libmcnt.so
$exportLD_PRELOAD="/tmp/libstr.so"
$ps
PIDTTYTIMECMD
2758pts/200:00:00bash
4371pts/200:00:00ps
malloccalled:184times
totalallocatedmemory:302599bytes

下面來看下PHP打樁演算法在使用時出現的問題。

當構造測試用例的數據,是在函數內部被另一個外部函數所使用時,我們需要忽略外部函數所帶來的影響。

需要進行「打樁」,舉一個具體的例子

classDataGetter{
public:
...
boolRun();
...
private:
...
Client*m_ptr_client;
...
};
.....
.....
boolDataGetter::Run(){
...
std::stringdata;
boolret=m_ptr_client->GetData(data);
...
}
....
....

比如要對run這個函數進行單元測試,它內部調用了ptr_client->GetData(data)的方法,它是通過tcp協議從服務端取數據到data里,測試run這個函數,必然要構造data。

如果不「打樁」,要測試的話,我們就需要再從服務端去構造數據,而且還可能收到其他因素的影響。

這時候「樁」就是很好的一種技術。

那如何去構造「樁」呢。

那麼如何構造呢?

原理:利用c++ virtual的特性,改變m_ptr_client指針所指向的對象,重寫一個「打樁」測試類。

當然,前提是GetData的定謹橋差義本身是virtual的消宏。

假設Client的定義如下

classClient{
......
public:
virtualboolGetData(std::string&data);
......
};

我們只需要重寫Getdata的方法,並且當參數data被傳進來時,我們可以返回特定的值。

這一套方法,google已經提供了很好的一套框架:gmock

下面介紹一下它的用法

#include"client.h"//被mock的類的頭文件
#include//gmock的頭文件
classMockClient:publicClient{
public:
MockClient():Client(){}
MOCK_METHOD1(GetData,bool(std::string&));
}

這里使用了一個宏MOCK_METHOD1

原形是MOCK_METHOD#1(#2, #3(#4) )

#1表示被mock的函數參數個數,#2表示被mock的函數名稱,#3表示被mock的函數返回值,#4表示被mock的函數參數列表

這樣,一個「樁」就「打」好了。

如何正確簡便地使用

首先,要先改變m_ptr_client指向的對象,對於private的變數,在前一章有描述方法,

然後測試的時候,直接將 m_ptr_client = new
MockClient()即可,不過要記得釋放它之前new的資源(如果有的話),不然就內存泄露了,哈哈

使用gmock的幾個宏,用一個例子簡單介紹下:

EXPECT_CALL(//mock被調用時,要發生的動作
*m_ptr_client,//被mock的對象,看清楚,是對象,不是指針了
GetData(test::_)//被mock的方法,參數為佔位符
).Times(2)//表示被調用2次
.WillOnce(第一次調用
testing::SetArgReferee<0>(「test」),//設置第0個參數的值為「test」
testing::Return(true),//設置返回值為true
)
.WillOnce(第二次調用
testing::SetArgReferee<0>(「test」),//設置第0個參數的值為「test」
testing::Return(false),//設置返回值為false
);

測試的原則,盡量不修改被測函數,覆蓋函數的每一個分支,保證外部條件都是正確的。

熱點內容
斯維爾加密狗 發布:2025-09-18 01:31:00 瀏覽:247
手把手win7搭建web伺服器 發布:2025-09-18 01:25:53 瀏覽:726
硬碟緩存128m 發布:2025-09-18 01:15:13 瀏覽:753
蘋果手機設備密碼是指什麼 發布:2025-09-18 01:02:26 瀏覽:467
asp門戶網站源碼 發布:2025-09-18 00:54:00 瀏覽:449
java資料庫例子 發布:2025-09-18 00:53:58 瀏覽:220
sh腳本輸出 發布:2025-09-18 00:48:10 瀏覽:258
我的世界伺服器箱里的東西沒了 發布:2025-09-18 00:39:20 瀏覽:934
java數字轉大寫 發布:2025-09-18 00:25:58 瀏覽:312
網路編程百度雲 發布:2025-09-18 00:19:52 瀏覽:125