mock重新编译
❶ 虚拟仿真提交实验数据失败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();
- public double getTotalPrice(){ Iteratorit=erator(); double price= ; while (it hasNext()){ =(SofareComponent)it next(); //自动递归调用各个对象的getTotalPrice方法并累加 price+=sofareComponent getTotalPrice(); } return price; }
- public double getTotalPrice(){ return price; }
- //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); }
- public void accept(Visitorvisitor);
- public void accept(Visitorvisitor){ visitor visitSofareSet( this ); Iteratorit=erator(); while (it hasNext()){ SofareComponentponent=(SofareComponent)it next(); ponent accept(visitor); } }
- public void accept(Visitorvisitor){ visitor visitBrand( this ); Iteratorit=erator(); while (it hasNext()){ SofareComponentponent=(SofareComponent)it next(); ponent accept(visitor); } }
- public void accept(Visitorvisitor){ visitor visitProct( this ); }
- 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; } }
- //建立一个新的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; } }
- 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); } }
- //建立一个新的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方法 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()); } //别的代码请参见随本文带的源程序 …… }
- //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
);
测试的原则,尽量不修改被测函数,覆盖函数的每一个分支,保证外部条件都是正确的。