Published on

ARTS 第37周

Authors
  • Algorithm: 942. DI String Match
  • Review: What is Test Driven Development (TDD)
  • Tip: Springboot logback profile
  • Share: 阮一峰的每周分享第52期

Algorithm

package org.nocoder.leetcode.solution;

/**
 * 942. DI String Match
 * <p>
 * Given a string S that only contains "I" (increase) or "D" (decrease), let N = S.length.
 * <p>
 * Return any permutation A of [0, 1, ..., N] such that for all i = 0, ..., N-1:
 * <p>
 * If S[i] == "I", then A[i] < A[i+1]
 * If S[i] == "D", then A[i] > A[i+1]
 * <p>
 * <p>
 * Example 1:
 * <p>
 * Input: "IDID"
 * Output: [0,4,1,3,2]
 * Example 2:
 * <p>
 * Input: "III"
 * Output: [0,1,2,3]
 * Example 3:
 * <p>
 * Input: "DDI"
 * Output: [3,2,0,1]
 * <p>
 * <p>
 * Note:
 * <p>
 * 1 <= S.length <= 10000
 * S only contains characters "I" or "D".
 *
 * @author jason
 * @date 2019/4/28.
 */
public class DIStringMatch {
    public static int[] diStringMatch(String s) {
        int n = s.length();
        int lo = 0, hi = n;
        int[] ans = new int[n + 1];
        for (int i = 0; i < n; ++i) {
            if (s.charAt(i) == 'I') {
                ans[i] = lo++;
            } else {
                ans[i] = hi--;
            }
        }

        ans[n] = lo;
        return ans;
    }

    public static void main(String[] args) {
        int[] arr = diStringMatch("IDID");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

Review

What is Test Driven Development (TDD)?

测试驱动开发从为应用程序的每个小功能设计和开发测试开始。在TDD方法中,首先,开发测试,指定并验证代码将执行的操作。

如何进行TDD测试

以下步骤定义了如何执行TDD

  1. 编写测试代码
  2. 运行所有测试,看看是否有任何新测试失败
  3. 编写业务逻辑代码
  4. 运行测试并重构代码
  5. 重复以上过程

关于TDD的一些说明:

  • TDD既不是“测试”也不是“设计”。
  • TDD并不意味着“编写一些测试,然后构建一个通过测试的系统。
  • TDD并不意味着“进行大量测试”。

Tip

Springboot logback profile

Springboot 默认的logging 配置可以将日志打印到控制台或者写出到文件,如果需要滚动归档,就可以用logback.xml来扩展日志功能了, 接下来我们需要实现不同的环境不同的日志配置,例如开发环境下直接打印到控制台,测试环境下打印日志到控制台并且输出到文件,生产环境只输出到文件。

Resource目录下创建xml配置文件,这样命名logback-spring.xml

官方的控制台打印日志配置了颜色,比较好看,可以引入springboot logging 包下的defaults.xml直接使用

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>./log/service-keeper.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%date [%thread] %-5level %logger{5} - %msg%n</pattern>
            <charset class="java.nio.charset.Charset">UTF-8</charset>
        </encoder>
    </appender>

    <springProfile name="dev">
        <logger name="org.nocoder.servicekeeper.infrastructure.repository" level="DEBUG"/>
        <root level="info">
            <appender-ref ref="CONSOLE"/>
            <!--<appender-ref ref="FILE"/>-->
        </root>
    </springProfile>

    <springProfile name="test">
        <logger name="org.nocoder.servicekeeper.infrastructure.repository" level="DEBUG"/>
        <root level="info">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="FILE"/>
        </root>
    </springProfile>

    <springProfile name="prod">
        <root level="info">
            <appender-ref ref="FILE"/>
        </root>
    </springProfile>
</configuration>

org/springframework/boot/logging/logback/defaults.xml

<?xml version="1.0" encoding="UTF-8"?>

<!--
Default logback configuration provided for import, equivalent to the programmatic
initialization performed by Boot
-->

<included>
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

    <logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
    <logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
    <logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
    <logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
    <logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
    <logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
    <logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
</included>

application.yml

spring:
  profiles:
    active: dev

配置好以后Resource 目录下的结构类似这样

└── resources
    ├── application-dev.yml
    ├── application-prod.yml
    ├── application-test.yml
    ├── application.yml
    ├── logback-spring.xml

Share

阮一峰的每周分享第52期