[JAVA] Efforts to improve the development efficiency of legacy in-house Web systems as much as possible

It was such a situation

Background and motive

I will be in charge of the project to add functions to the above "legacy" in-house Web system. I want to make the system as close as possible to an "impressive" system. However, in the absence of test code and documentation, it is difficult to make a big deal. We are considering replacing the entire system, but it is NG due to cost issues. ..

I quietly faced the reality and started to start development, but as I proceeded with development, I noticed the following issues.

It was also such a situation

  1. Insufficient source code management 惻 Not impressed
  1. No build tools installed (Java)
  1. The IP address setting of the linked system is described in the configuration file (PHP)
  1. Local development environment is not maintained

Therefore, instead of refactoring the application code itself, the purpose is to improve the development efficiency as much as possible by improving the development environment as described above (strictly speaking, there are items related to code modification ..). Originally, the team (3 people) made some efforts.

Purpose of the article

For those who are in charge of similar legacy systems, there are two things that can be a hint for improvement, and if it is a new system or a relatively new system, it will be an initiative that should be adopted by all means. I will post in the meaning.

important point

Initiatives

1. Version control with Git

I was already using GitLab with my team, so I had no choice but to move to Git. I migrated from Subversion to Git using git-svn. Complete immediately with git svn clone. I thought, but I had a hard time because the subversion repository server used a non-standard port for ssh.

Eventually I copied the subversion repository (the directory containing conf, db, hooks, etc.) and ran the git svn command on that directory.

$ git svn clone -s  --prefix=svn/ file://[Directory where the repository is saved]

For PHP programs, we asked the operations team to obtain the production code and committed it as the latest source.

2. Introduction of build tools (Java)

The fact that you can't use any IDE other than Eclipse has been a problem for our team, who recently introduced IntelliJ. In addition, it is difficult to share GUI operation procedures within the person in charge and pass them on to future generations. .. Since the team has a track record of using Gradle, we also considered introducing Gradle in this project. By introducing Gradle, it is possible to manage the part corresponding to the above GUI operation with the setting file (build.gradle), and the same result regardless of who executes it by just hitting one command described later. Because things can be generated. However, considering that it is related to the behavior of the entire program and the regression test cannot be performed sufficiently, it should be limited to use in the local development environment, and the final test and deployment should be as before. The condition that the module generated by the build of is used, and the build tool was introduced.

In addition, JDK8 is used to execute Gradle.

Investigate dependent libraries

In order to introduce Gradle, it was necessary to investigate the existing dependent libraries and list them in dependencies of build.gradle. Maven repository search site (here, etc.) by referring to Ź»Implementation-Version of MANIFEST.MFand the file name in each jar file of the dependent library directory in the source code. I investigated the contents to be described inbuild.gradleusing and made the description. (For those that cannot be obtained from the outside, some local jar files were specified usingcompile files ()`)

build.gradle It turned out to be something like this

build.gradle


plugins {
    id "war"
}

sourceCompatibility = '1.5'
targetCompatibility = '1.5'

sourceSets { //It had to be set because it had a special directory structure.
    main {
        java { srcDir 'WEB-INF/src/main/java' }
        resources { srcDir 'WEB-INF/src/main/resources' }
    }
    test {
        java { srcDir 'WEB-INF/src/test/java' }
        resources { srcDir 'WEB-INF/src/test/resources' }
    }
}

repositories { //Adding the source of the library that cannot be obtained from mavenCentral
    maven { url "http://maven.imagej.net/content/repositories/public/" }
    mavenCentral()
    maven { url "http://repo.metova.com/nexus/content/groups/public/" }
    maven { url "https://www.seasar.org/maven/maven2/" }
}

dependencies {
    compile 'javax.activation:activation:1.0.2'
    compile 'aopalliance:aopalliance:1.0'
    compile 'commons-codec:commons-codec:1.3'
...
    compile files('WEB-INF/lib/h2-2007-04-29.jar')
...
    compile 'org.seasar.dao:s2-dao:1.0.46'
    compile 'org.seasar.dao:s2-dao-tiger:1.0.46'
...
}

Build

By executing the following command, the war file required for deployment will be created.

$ ./gradlew build

3. Linkage system IP address switching by environment variables (PHP)

The IP address of the linked system is different for each of the local development environment, staging environment, and production environment, but in the past, after deploying to each environment, switching work was done manually one by one. If there are one or two linked systems, it may not be a problem, but as the number increases, the work becomes troublesome, and in the unlikely event that the settings are incorrect (accidentally connected to the production environment). The risk of accidents) also increases.

Therefore, I modified it so that it behaves like the environment variable is acquired in the PHP program and the value of the variable used in the program is switched accordingly.

define('APP_ENV', getenv('APP_ENV'));
if (APP_ENV === 'local') {
    $urlA = "http://localhost/appA.php";
    $urlB = "http://localhost/appB.php";
...
} elseif (APP_ENV === 'staging') {
    $urlA = "http://staging.example.com/appA.php";
    $urlB = "http://staging.example.com/appB.php";
...
} elseif (APP_ENV === 'production') {
...

Also, in the staging environment and production environment, the following was added to the apache configuration file so that environment variables are set.

<VirtualHost *:80>
...
SetEnv APP_ENV staging #Postscript part production in the case of production
...
</VirtualHost>

4. Development of local development environment using Docker

In addition to setting up various execution environments, I was also considering introducing a PHP debugger (xdebug), so I thought it would be very troublesome to build an environment for each person, so I decided to use Docker to set up a local development environment. ..

Java-Tomcat local development environment

Dockerfile


FROM centos:latest

ADD jdk-1_5_0_22-linux-amd64.bin /root/
RUN set -x && \
    echo yes | /root/jdk-1_5_0_22-linux-amd64.bin
ENV JAVA_HOME=/jdk1.5.0_22 \
    PATH=$PATH:/jdk1.5.0_22/bin

ADD apache-tomcat-6.0.9.tar.gz /root/
ENV CATALINA_HOME=/root/apache-tomcat-6.0.9

EXPOSE 8080
CMD ["/root/apache-tomcat-6.0.9/bin/catalina.sh", "run"]

docker-compose.yml


java-docker:
  image: ...
  ports:
    - "8080:8080"
  volumes:
    # 2.If you place the war file built in in the same directory, it will be deployed.
    - "${PWD}/app.war:/root/apache-tomcat-6.0.9/webapps/app.war"
  environment:
    - TZ=Asia/Tokyo #It is convenient to set the time zone specification log output etc.
  restart: always

PHP local development environment

Dockerfile


FROM centos:7.4.1708

RUN set -x && \
  yum update -y && \
  yum install apache php php-devel php-pear gcc make -y

RUN set -x && \
  pecl install xdebug-2.4.1

ADD xdebug.ini /etc/php.d/

RUN ln -sfT /dev/stdout "/var/log/httpd/access_log" && \
    ln -sfT /dev/stderr "/var/log/httpd/error_log"

EXPOSE 80

CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]

docker-compose.yml


php-docker:
  image: ...
  ports:
    - "80:80"
  volumes:
    - "${PWD}/../srcDir:/var/www/html"
  environment:
    - APP_ENV=local # 3.Environment variables
    - TZ=Asia/Tokyo #Specifying the time zone
  restart: always

I also pushed the container images generated by building these to a private repository (Docker Registry).

as a result

$ docker pull ...

It is now possible to build a local development / debugging environment for the entire team with a single command. (Although it was necessary to manually handle the subsequent IDE integration ...)

Summary

It is a difficult question how much to spend on a system that you do not know how long it will last. (Especially for 2., I feel that the benefits have not been received so much despite the time and effort it took.)

As I mentioned at the beginning, I think that the decision on how much to do and what to do will change depending on the project, because this initiative has a section that I actively worked on while also studying my own technical skills.

I want to develop an exciting service using the latest technology using a high-performance machine. However, the reality does not seem to be so sweet. ..

Recommended Posts

Efforts to improve the development efficiency of legacy in-house Web systems as much as possible
Efforts to gradually improve the large-scale legacy system of tabelog
The story of dieting the container of the Elixir application as much as possible
Improve the performance of your Docker development environment
Roughly the flow of web application development with Rails.