当前位置: 首页 > news >正文

淘宝天猫优惠券网站建设费用跨境电商排名

淘宝天猫优惠券网站建设费用,跨境电商排名,惠州网站建设制作公司,上海互联网公司有哪些文章目录 第十六章 代码校验1. 测试1.1 单元测试1.2 JUnit1.3 测试覆盖率的幻觉 2. 前置条件2.1 断言#xff08;Assertions#xff09;2.2 Java 断言语法2.3 Guava 断言2.4 使用断言进行契约式设计2.4.1 检查指令2.4.2 前置条件2.4.3 后置条件2.4.4 不变性2.4.5 放松 DbC 检… 文章目录 第十六章 代码校验1. 测试1.1 单元测试1.2 JUnit1.3 测试覆盖率的幻觉 2. 前置条件2.1 断言Assertions2.2 Java 断言语法2.3 Guava 断言2.4 使用断言进行契约式设计2.4.1 检查指令2.4.2 前置条件2.4.3 后置条件2.4.4 不变性2.4.5 放松 DbC 检查或非严格的 DbC2.4.6 使用 Guava 前置条件 3. 测试驱动开发4. 日志4.1 日志会给出正在运行的程序的各种信息。4.2 日志等级 5. 调试5.1 使用 JDB 调试5.2 图形化调试器 6. 基准测试6.1 微基准测试6.2 JMH 的引入 7. 剖析和优化7.1 优化准则 8. 风格检测9. 静态错误分析10. 代码重审11. 结对编程12. 重构12.1 重构基石 13. 持续集成14. 本章小结 第十六章 代码校验 你永远不能保证你的代码是正确的你只能证明它是错的。 1. 测试 如果没有测试过它就是不能工作的。 Java是一个静态类型的语言但静态类型检查是一种非常局限性的测试只是说明编译器接受你代码中的语法和基本类型规则并不意味着你的代码达到程序的目标。 1.1 单元测试 “单元”是指测试一小部分代码 。通常每个类都有测试来检查它所有方法的行为。“系统”测试则是不同的它检查的是整个程序是否满足要求。 1.2 JUnit 在 JUnit 最简单的使用中使用 Test 注解标记表示测试的每个方法。JUnit 将这些方法标识为单独的测试并一次设置和运行一个测试采取措施避免测试之间的副作用。 package validating;import java.util.ArrayList;public class CountedList extends ArrayListString {private static int counter 0;private int idcounter;public CountedList() {System.out.println(CountedList # id);}public int getId() {return id;} }package validating;import org.junit.jupiter.api.*;import java.util.Arrays; import java.util.List;import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals;public class CountedListTest {private CountedList list;BeforeAllstatic void beforeAllMsg() {System.out.println( Starting CountedListTest);}AfterAllstatic void afterAllMsg() {System.out.println( Finished CountedListTest);}BeforeEachpublic void initialize() {list new CountedList();System.out.println(Set up for list.getId());for (int i 0; i 3; i) {list.add(Integer.toString(i));}}AfterEachpublic void cleanup() {System.out.println(Cleaning up list.getId());}Testpublic void insert() {System.out.println(Running testInsert());assertEquals(list.size(), 3);list.add(1, Insert);assertEquals(list.size(), 4);assertEquals(list.get(1), Insert);}Testpublic void replace() {System.out.println(Running testReplace());assertEquals(list.size(), 3);list.set(1, Replace);assertEquals(list.size(), 3);assertEquals(list.get(1), Replace);}private void compare(ListString lst, String[] strs) {assertArrayEquals(lst.toArray(new String[0]), strs);}Testpublic void order() {System.out.println(Running testOrder());compare(list, new String[]{0, 1, 2});}Testpublic void remove() {System.out.println(Running testRemove());assertEquals(list.size(), 3);list.remove(1);assertEquals(list.size(), 2);compare(list, new String[]{0, 2});}Testpublic void addAll() {System.out.println(Running testAddAll());list.addAll(Arrays.asList(new String[]{An, African, Swallow}));assertEquals(list.size(), 6);compare(list, new String[]{0, 1, 2, An, African, Swallow});} }输出 Starting CountedListTest CountedList #0 Set up for 0 Running testAddAll() Cleaning up 0 CountedList #1 Set up for 1 Running testInsert() Cleaning up 1 CountedList #2 Set up for 2 Running testRemove() Cleaning up 2 CountedList #3 Set up for 3 Running testOrder() Cleaning up 3 CountedList #4 Set up for 4 Running testReplace() Cleaning up 4Finished CountedListTestBeforeAll 注解是在任何其他测试操作之前运行一次的方法。 AfterAll 是所有其他测试操作之后只 运行一次的方法。两个方法都必须是静态的。 BeforeEach注解是通常用于创建和初始化公共对象的方法并在每次测试前运行。可以将所有这样 的初始化放在测试类的构造函数中。 —PSBeforeAll 是只运行一次BeforeEach 是每次都运行例子中有5个 Test 注释的方法BeforeEach 就运行了5次 JUnit 使用 Test 注解发现这些方法并将每个方法作为测试运行。在方法内部你可以执行任何所需的操作并使用 JUnit 断言方法以assert开头验证测试的正确性更全面的assert说明可以在 Junit 文档里找到。如果断言失败将显示导致失败的表达式和值。 1.3 测试覆盖率的幻觉 测试覆盖率同样也称为代码覆盖率度量代码的测试百分比。百分比越高测试的覆盖率越大。 对于没有知识但处于控制地位的人来说很容易在没有任何了解的情况下也有概念认为 100% 的测试覆盖是唯一可接受的值。这有一个问题因为 100% 并不意味着是对测试有效性的良好测量。你可以测试所有需要它的东西但是只需要 65% 的覆盖率。如果需要 100% 的覆盖你将浪费大量时间来生成剩余的代码并且在向项目添加代码时浪费的时间更多。 当分析一个未知的代码库时测试覆盖率作为一个粗略的度量是有用的。如果覆盖率工具报告的值特别低比如少于百分之40则说明覆盖不够充分。然而一个非常高的值也同样值得怀疑这表明对编程领域了解不足的人迫使团队做出了武断的决定。覆盖工具的最佳用途是发现代码库中未测试的部分。但是不要依赖覆盖率来得到测试质量的任何信息。 —PS我有理由怀疑在内涵什么 2. 前置条件 前置条件的概念来自于契约式设计(Design By Contract, DbC), 利用断言机制实现。 2.1 断言Assertions 断言通过验证在程序执行期间满足某些条件从而增加了程序的健壮性。举例假设在一个对象中有一个数值字段表示日历上的月份。这个数字总是介于 1-12 之间。断言可以检查这个数字如果超出了该范围则报告错误。如果在方法的内部则可以使用断言检查参数的有效性。这些是确保程序正确的重要测试但是它们不能在编译时被检查并且它们不属于单元测试的范围。 2.2 Java 断言语法 断言语句有两种形式 : assert boolean-expression assert boolean-expression: information-expression; 2.3 Guava 断言 因为启用 Java 本地断言很麻烦Guava 团队添加一个始终启用的用来替换断言的 Verify 类。 2.4 使用断言进行契约式设计 契约式设计*(DbC)*是 Eiffel 语言的发明者 Bertrand Meyer 提出的一个概念通过确保对象遵循某些规则来帮助创建健壮的程序。 Meyer 认为 1.应该明确指定行为就好像它是一个契约一样。 2.通过实现某些运行时检查来保证这种行为他将这些检查称为前置条件、后置条件和不变项。 2.4.1 检查指令 详细研究 DbC 之前思考最简单使用断言的办法Meyer 称它为检查指令。检查指令说明你确信代码中的某个特定属性此时已经得到满足。 在化学领域你也许会用一种纯液体去滴定测量另一种液体当达到一个特定的点时液体变蓝了。 从两个液体的颜色上并不能明显看出这是复杂反应的一部分。滴定完成后一个有用的检查指令是能够断定液体变蓝了。 检查指令是对你的代码进行补充当你可以测试并阐明对象或程序的状态时应该使用它。 2.4.2 前置条件 前置条件确保客户端(调用此方法的代码)履行其部分契约。这意味着在方法调用开始时几乎总是会检查参数在你用那个方法做任何操作之前以此保证它们的调用在方法中是合适的。因为你永远无法知道客户端会传递给你什么前置条件是确保检查的一个好做法。 —PScheckdata 2.4.3 后置条件 后置条件测试你在方法中所做的操作的结果。这段代码放在方法调用的末尾在 return 语句之前(如果有的话)。对于长时间、复杂的方法在返回计算结果之前需要对计算结果进行验证也就是说在某些情况下由于某种原因你不能总是相信结果)后置条件很重要但是任何时候你可以描述方法结果上的约束时最好将这些约束在代码中表示为后置条件。 —PSreview 2.4.4 不变性 不变性保证了必须在方法调用之间维护的对象的状态。但是它并不会阻止方法在执行过程中暂时偏离这些保证它只是在说对象的状态信息应该总是遵守状态规则 1. 在进入该方法时。 2. 在离开方法之前。 此外不变性是构造后对于对象状态的保证。 根据这个描述一个有效的不变性被定义为一个方法可能被命名为 invariant() 它在构造之后以及每个方法的开始和结束时调用。方法以如下方式调用 assert invariant(); 2.4.5 放松 DbC 检查或非严格的 DbC 尽管 Meyer 强调了前置条件、后置条件和不变性的价值以及在开发过程中使用它们的重要性他承认在一个产品中包含所有 DbC 代码并不总是实际的。你可以基于对特定位置的代码的信任程度放松 DbC 检查。 2.4.6 使用 Guava 前置条件 谷歌的 Guava 库包含了一组很好的前置条件测试这些测试不仅易于使用而且命名也足够好。 首先引入依赖 dependencygroupIdcom.google.guava/groupIdartifactIdguava/artifactIdversion21.0/version/dependencyimport java.util.function.Consumer;import static com.google.common.base.Preconditions.*;public class GuavaPreconditions {static void test(ConsumerString c, String s) {try {System.out.println(s);c.accept(s);System.out.println(Success);} catch (Exception e) {String type e.getClass().getSimpleName();String msg e.getMessage();System.out.println(type (msg null ? : : msg));}}public static void main(String[] args) {test(s - s checkNotNull(s), X);test(s - s checkNotNull(s), null);test(s - s checkNotNull(s, s was null), null);test(s - s checkNotNull(s, s was null, %s %s, arg2, arg3), null);test(s - checkArgument(s Fozzie), Fozzie);test(s - checkArgument(s Fozzie), X);test(s - checkArgument(s Fozzie), null);test(s - checkArgument(s Fozzie, Bear Left!), null);test(s - checkArgument(s Fozzie, Bear Left! %s Right!, Frog), null);test(s - checkState(s.length() 6), Mortimer);test(s - checkState(s.length() 6), Mort);test(s - checkState(s.length() 6), null);test(s - checkElementIndex(6, s.length()), Robert);test(s - checkElementIndex(6, s.length()), Bob);test(s - checkElementIndex(6, s.length()), null);test(s - checkPositionIndex(6, s.length()), Robert);test(s - checkPositionIndex(6, s.length()), Bob);test(s - checkPositionIndex(6, s.length()), null);test(s - checkPositionIndexes(0, 6, s.length()), Hieronymus);test(s - checkPositionIndexes(0, 10, s.length()), Hieronymus);test(s - checkPositionIndexes(0, 11, s.length()), Hieronymus);test(s - checkPositionIndexes(-1, 6, s.length()), Hieronymus);test(s - checkPositionIndexes(7, 6, s.length()), Hieronymus);test(s - checkPositionIndexes(0, 6, s.length()), null);} }输出 X Success null NullPointerException null NullPointerException: s was null null NullPointerException: s was null, arg2 arg3 Fozzie Success X IllegalArgumentException null IllegalArgumentException null IllegalArgumentException: Bear Left! null IllegalArgumentException: Bear Left! Frog Right! Mortimer Success Mort IllegalStateException null NullPointerException Robert IndexOutOfBoundsException: index (6) must be less than size (6) Bob IndexOutOfBoundsException: index (6) must be less than size (3) null NullPointerException Robert Success Bob IndexOutOfBoundsException: index (6) must not be greater than size (3) null NullPointerException Hieronymus Success Hieronymus Success Hieronymus IndexOutOfBoundsException: end index (11) must not be greater than size (10) Hieronymus IndexOutOfBoundsException: start index (-1) must not be negative Hieronymus IndexOutOfBoundsException: end index (6) must not be less than start index (7) null NullPointerException每个前置条件都有三种不同的重载形式一个什么都没有一个带有简单字符串消息以及带有一个字符串和替换值。 在上面的例子中演示了 checkNotNull() 和 checkArgument() 这两种形式。但是它们对于所有前置条件方法都是相同的。注意 checkNotNull() 的返回参数 所以你可以在表达式中内联使用它。下面是如何在构造函数中使用它来防止包含 Null 值的对象构造 import static com.google.common.base.Preconditions.checkNotNull;public class NonNullConstruction {private Integer n;private String s;public NonNullConstruction(Integer n, String s) {this.n checkNotNull(n);this.s checkNotNull(s);}public static void main(String[] args) {NonNullConstruction nnc new NonNullConstruction(3, Trousers);} }checkArgument() 接受布尔表达式来对参数进行更具体的测试 失败时抛出 IllegalArgumentException checkState() 用于测试对象的状态例如不变性检查而不是检查参 数并在失败时抛出 IllegalStateException 。 最后三个方法在失败时抛出 IndexOutOfBoundsException checkElementIndex() 确保其第一个参数是列表、字符串或数组的有效元素索引其大小由第二个参数指定 checkPositionIndex() 确保它的第一个参数在 0 到第二个参数(包括第二个参数)的范围内。 checkPositionIndexes() 检查 [first_arg, second_arg] 是一个列表的有效子列表由第三个参数指定大小的字符串或数组。 3. 测试驱动开发 之所以可以有测试驱动开发TDD这种开发方式是因为如果你在设计和编写代码时考虑到了测试那么你不仅可以写出可测试性更好的代码而且还可以得到更好的代码设计。 纯粹的 TDD 主义者会在实现新功能之前就为其编写测试这称为测试优先的开发。 测试驱动 vs. 测试优先 虽然我自己还没有达到测试优先的意识水平但我最感兴趣的是来自测试优先中的“测试失败的书签”这一概念。 当你离开你的工作一段时间后重新回到工作进展中甚至找到你离开时工作到的地方有时会很有挑战性。 然而以失败的测试为书签能让你找到之前停止的地方。 这似乎让你能更轻松地暂时离开你的工作因为不用担心找不到工作进展的位置。 纯粹的测试优先编程的主要问题是它假设你事先了解了你正在解决的问题。 根据我自己的经验我通常是从实验开始而只有当我处理问题一段时间后我对它的理解才会达到能给它编写测试的程度。 —PS这个要求有点高 当然偶尔会有一些问题在你开始之前就已经完全定义但我个人并不常遇到这些问题。 实际上可能用“面向测试的开发 ( Test-Oriented Development )”这个短语来描述编写测试良好的代码或许更好。 4. 日志 4.1 日志会给出正在运行的程序的各种信息。 在调试程序中日志可以是普通状态数据用于显示程序运行过程例如安装程序可能会记录安装过程中采取的步骤存储文件的目录程序的启动值等。 业内普遍认为标准 Java 发行版本中的日志包 (java.util.logging) 的设计相当糟糕。 大多数人会选择其他的替代日志包。如 Simple Logging Facade for Java(SLF4J) ,它为多个日志框架提供了一个封装好的调用方式这些日志框架包括 java.util.logging logback 和 log4j 。 SLF4J 允许用户在部署时插入所需的日志框架。 import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class SLF4JLogging {private static Logger log LoggerFactory.getLogger(SLF4JLogging.class);public static void main(String[] args) {log.info(hello logging);} }输出 14:07:59.401 [main] INFO validating.SLF4JLogging - hello logging4.2 日志等级 SLF4J 提供了多个等级的日志消息。下面这个例子以“严重性”的递增顺序对它们作出演示 import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class SLF4JLevels {private static Logger log LoggerFactory.getLogger(SLF4JLevels.class);public static void main(String[] args) {log.trace(Hello);log.debug(Logging);log.info(Using);log.warn(the SLF4J);log.error(Facade);} }输出 15:07:50.873 [main] DEBUG validating.SLF4JLevels - Logging 15:07:50.875 [main] INFO validating.SLF4JLevels - Using 15:07:50.875 [main] WARN validating.SLF4JLevels - the SLF4J 15:07:50.875 [main] ERROR validating.SLF4JLevels - Facade5. 调试 使用 System.out 或日志信息能给我们带来对程序行为的有效见解但对于困难问题来说这种方式就显得笨拙且耗时了。 此时你需要调试器。除了比打印语句更快更轻易地展示信息以外调试器还可以设置断点并在程序运行到这些断点处暂停程序。 使用调试器可以展示任何时刻的程序状态查看变量的值一步一步运行程序连接远程运行的程序等等。 5.1 使用 JDB 调试 Java 调试器JDB是 JDK 内置的命令行工具。从调试的指令和命令行接口两方面看的话JDB 至少从概念上是 GNU 调试器GDB受 Unix DB 的影响的继承者。 public class SimpleDebugging {private static void foo1() {System.out.println(In foo1);foo2();}private static void foo2() {System.out.println(In foo2);foo3();}private static void foo3() {System.out.println(In foo3);int j 1;j--;int i 5 / j;}public static void main(String[] args) {foo1();} }输出 In foo1 In foo2 In foo3 Exception in thread main java.lang.ArithmeticException: / by zeroat validating.SimpleDebugging.foo3(SimpleDebugging.java:23)at validating.SimpleDebugging.foo2(SimpleDebugging.java:16)at validating.SimpleDebugging.foo1(SimpleDebugging.java:11)at validating.SimpleDebugging.main(SimpleDebugging.java:27)为了运行 JDB你需要在编译 SimpleDebugging.java 时加上 -g 标记从而告诉编译器生成编译信息。然后使用如下命令开始调试程序 另开一篇开发技术-使用 JDB 调试 5.2 图形化调试器 使用类似 JDB 的命令行调试器是不方便的。使用图形化调试器能更加高效、更快速地追踪 bug。IBM 的 EclipseOracle 的 NetBeans 和 JetBrains 的 IntelliJ 这些集成开发环境都含有面向 Java 语言的好用的图形化调试器。 6. 基准测试 我们应该忘掉微小的效率提升说的就是这些 97% 的时间做的事过早的优化是万恶之源。 —— Donald Knuth 通常一个简单直接的编码方法就足够好了。如果你进行了不必要的优化就会使你的代码变得无谓的复杂和难以理解。 基准测试意味着对代码或算法片段进行计时看哪个跑得更快。 6.1 微基准测试 写一个计时工具类从而比较不同代码块的执行速度是具有吸引力的。看上去这会产生一些有用的数据。比如这里有一个简单的 Timer 类可以用以下两种方式使用它 import static java.util.concurrent.TimeUnit.NANOSECONDS;public class Timer {// PS获取时间戳纳秒级private long start System.nanoTime();// PS产生以毫秒为单位的运行时间public long duration() {return NANOSECONDS.toMillis(System.nanoTime() - start);}public static long duration(Runnable test) {Timer timer new Timer();test.run();return timer.duration();} }import java.util.Arrays;public class BadMicroBenchmark {static final int SIZE 250_000_000;public static void main(String[] args) {try {long[] la new long[SIZE];System.out.println(setAll: Timer.duration(() - Arrays.setAll(la, n - n)));System.out.println(parallelSetAll: Timer.duration(() - Arrays.parallelSetAll(la, n - n)));} catch (OutOfMemoryError e) {System.out.println(Insufficient memory);System.exit(0);}} }输出 setAll: 188 parallelSetAll: 1656.2 JMH 的引入 截止目前为止唯一能产生像样结果的 Java 微基准测试系统就是 Java Microbenchmarking Harness简称 JMH。 7. 剖析和优化 剖析器可以找到这些导致程序慢的地方剖析器收集的信息能显示程序哪一部分消耗内存哪个方法最耗时。一些剖析器甚至能关闭垃圾回收从而帮助限定内存分配的模式剖析器还可以帮助检测程序中的线程死锁。 安装 Java 开发工具包JDK时会顺带安装一个虚拟的剖析器叫做 VisualVM。 7.1 优化准则 避免为了性能牺牲代码的可读性。 不要独立地看待性能。衡量与带来的收益相比所需投入的工作量。 程序的大小很重要。性能优化通常只对运行了长时间的大型项目有价值。性能通常不是小项目的关注点。 运行起来程序比一心钻研它的性能具有更高的优先级。一旦你已经有了可工作的程序如有必要的话你可以使用剖析器提高它的效率。只有当性能是关键因素时才需要在设计/开发阶段考虑性能。 不要猜测瓶颈发生在哪。运行剖析器让剖析器告诉你。 无论何时有可能的话显式地设置实例为 null 表明你不再用它。这对垃圾收集器来说是个有用的暗示。 static final 修饰的变量会被 JVM 优化从而提高程序的运行速度。因而程序中的常量应该声明 static final。 —PS程序能跑起来再说其他 8. 风格检测 当你在一个团队中工作时(包括尤其是开源项目)让每个人遵循相同的代码风格是非常有帮助的。这样阅读项目的代码时不会因为风格的不同产生思维上的中断。幸运的是存在可以指出你代码中不符合风格准则的工具。 一个流行的风格检测器是 Checkstyle。 —PS制定准则不难难的是怎么让人遵守 9. 静态错误分析 尽管 Java 的静态类型检测可以发现基本的语法错误其他的分析工具可以发现躲避 javac 检测的更加 复杂的bug。一个这样的工具叫做 Findbugs。 10. 代码重审 代码重审是一个或一群人的一段代码被另一个或一群人阅读和评估的众多方式之一。它的目标是找到程序中的错误代码重审是最成功的能做到这点的途径之一。可惜的是它们也经常被认为是“过于昂贵的”有时这会成为程序员避免代码被重审时感到尴尬的借口。 11. 结对编程 结对编程是指两个程序员一起编程的实践活动。通常来说一个人“驱动”敲击键盘输入代码另一人观察者或指引者重审和分析代码同时也要思考策略。这产生了一种实时的代码重审。通常程序员会定期地互换角色。 结对编程有很多好处但最显著的是分享知识和防止阻塞。 有时很难向管理人员们推行结对编程因为他们可能觉得两个程序员解决同一个问题的效率比他们分开解决不同问题的效率低。尽管短期内是这样但是结对编程能带来更高的代码质量产生更高的生产力。 12. 重构 技术负债是指迭代发展的软件中为了应急而生的丑陋解决方案从而导致设计难以理解代码难以阅读的部分。特别是当你必须修改和增加新特性的时候这会造成麻烦。 —PSshit山 重构可以矫正技术负债。重构的关键是它能改善代码设计结构和可读性因而减少代码负债但是它不能改变代码的行为。 很难向管理人员推行重构“我们将投入很多工作不是增加新的特性当我们完成时外界无感知变化。”。不幸的是管理人员意识到重构的价值时都为时已晚了 当他们提出增加新的特性时你不得不告诉他们做不到因为代码基底已经埋藏了太多的问题试图增加新特性可能会使软件崩溃即使你能想出怎么做。 12.1 重构基石 在开始重构代码之前你需要有以下三个系统的支撑 测试通常JUnit 测试作为最小的根基因此你能确保重构不会改变代码的行为。 自动构建因而你能轻松地构建代码运行所有的测试。 版本控制以便你能回退到可工作的代码版本能够一直记录重构的每一步。 13. 持续集成 在软件开发的早期人们只能一次处理一步每个开发阶段无缝进入下一个。这种错觉经常被称为软件开发中的“瀑布流模型”。 产品本身经常也不是对客户有价值的事物。有时一大堆的特性完全是浪费时间因为创造出这些特性需求的人不是客户而是其他人。 上游团队的延期传递到下游团队当到了需要进行测试和集成的时候这些团队被指望赶上预期时间当他们必然做不到时就认为他们是“差劲的团队成员”。 另外商学院培养出的管理人员仍然被训练成只在已有的流程上做一些改动。 终于一些编程领域的人们再也忍受不了这种情况并开始进行实验。最初一些实验叫做“极限编程”因为它们与工业时代的思想完全不同。这些实验逐渐形成了如今显而易见的观点——尽管非常小——即把生产可运作的产品交到客户手中询问他们 (A) 是否想要它 (B) 是否喜欢它工作的方式 © 还希望有什么其他有用的功能特性。然后这些信息反馈给开发从而继续产出一个新版本。版本不断迭代项目最终演变成为客户带来真正价值的事物。 这完全颠倒了瀑布流开发的方式。每件事从开始到结束必须都在进行——即使一开始产品几乎没有任何特性。这么做对于在 开发周期的早期发现更多问题有巨大的益处。此外不是做大量宏大超前的计划和花费时间金钱在许多无用的特性上而是一直都能从顾客那得到反馈。当客户不再需要其他特性时你就完成了。这节省了大量的时间和金钱并提高了顾客的满意度。 有许多不同的想法导向这种方式但是目前首要的术语叫持续集成CI。 —PS瀑布流开发只能一步接着一步一个环节的延期后延续到后面的环节在前期可能会花费巨大的成本去做计划和调研结果做出来的产品包含了许多对客户无用的特性。CI 就是为了解决以上的问题每次快速交付小功能为客户再根据客户的反馈及需求进行下一步开发。 当前 CI 技术的高峰是持续集成服务器。正如重构一样持续集成需要分布式版本管理自动构建和自动测试系统作为基础。通常来说CI 服务器会绑定到你的版本控制仓库上。当 CI 服务器发现仓库中有改变时就会拉取最新版本的代码并按照 CI 脚本中的过程处理。接着它会执行脚本中定义的构建和测试操作通常脚本中使用的命令与人们在安装和测试中使用的命令完全相同。如果执行成功或失败CI 服务器会有许多种方式汇报给你包括在你的代码仓库上显示一个简单的标记。 —PS一般使用的工具有 Git Gitlab Maven Jenkins 即常说的流水线发布那一套 14. 本章小结 代码校验不是单一的过程或技术。每种方法只能发现特定类型的 bug作为程序员的你在开发过程中会明白每个额外的技术都能增加代码的可靠性和鲁棒性。校验不仅能在开发过程中还能在为应用添加 新功能的整个项目期间帮你发现更多的错误。现代化开发意味着比仅仅编写代码更多的内容每种你在开发过程中融入的测试技术—— 包括而且尤其是你创建的能适应特定应用的自定义工具——都会带来更好、更快和更加愉悦的开发过程同时也能为客户提供更高的价值和满意度体验。 自我学习总结 单元测试简单理解为测试每一个方法常用的 Java 单元测试框架为 JUnit它包含的注解有 Test BeforeAll AfterAll BeforeEach AfterEach测试覆盖率并不是需要达到 100%因为性价比不高契约式设计*(DbC)*包含前置条件、后置条件、不变项等检查谷歌的 Guava 库包含了一组很好的前置条件测试这些测试不仅易于使用而且命名也足够好大佬都是测试优先日志相关推荐一篇大佬的文章Java日志框架日志门面介绍SLF4J 日志等级从低到高为trace debug info warn error代码优化要遵循准则一个好的开发应该做好单元测试、遵循良好的开发规范一个好的项目组还需要做好代码重审好听的叫技术负债不好听就是代码屎山重构就是还债费时费力不重构的话系统越来越沉重。CI 每次快速交付小功能为客户再根据客户的反馈及需求进行下一步开发 图网侵删
http://www.dnsts.com.cn/news/173193.html

相关文章:

  • 用dz做网站怎么设置数据库位置图片在线制作
  • 俞润装饰做哪几个网站人工智能网站应怎么做
  • 做网站算新媒体运营吗手机建模软件
  • 门户网站建设基础术语网络广告视频
  • wordpress 5.0.3文章编辑昆明seo网站
  • 吴江和城乡建设局网站常德网站开发服务
  • 免费自助建站系统如何建立公司官网
  • 企业网站建设入账广州镭拓科技网站建设公司
  • 可以做动画的网站怎么用dw做网站
  • 做网站和开发app有什么不同菲律宾做网站好吗
  • 怎么找回网站达县网站制作
  • 电子商务的网站怎么做江苏住房与城乡建设部网站
  • 建设部网站规范下载上海网站建设 分类广告
  • 给wordpress网站做ssl卸载网页版微信登录手机会显示吗
  • 企业网站管理系统推荐互联网大厂一般指哪些公司
  • 十大免费数据网站网络推广策略的种类
  • 亚马逊网站网址股权融资
  • 网站建设项目策划书模板范文哪家网站设计比较好
  • 怎么样做个网站吉林科技网站建设
  • 网站发布之后上传文件路径变了360建筑网电脑版
  • asp网站没有数据库橙云的主机支持放两个网站吗
  • 宁海有做网站的吗静态网站的好处
  • 大圣网站建设xampp wamp wordpress
  • 网站开发需求调研网站建设职业发展前景
  • 闽清县建设局网站营销计划怎么写
  • 河源网站seo厦门市建设局网站文件
  • 宝安中心医院上班时间seo管理系统易语言
  • 做照片书哪个网站好突出什么 加强网站建设
  • 网站推广成本科技公司 网站模板
  • 电商网站设计周志seowhy什么意思