zenet_logo

-株式会社ゼネット技術ブログ-

【エラー】Javaのfor文とJavaScriptのfor文を混同したら大変な事態に!解決方法を説明します【解決】

はじめまして。ゼネットの佐藤です。

新人として現在Java研修を受講しており、その中でJavaとJavaScriptを混同して使用したことで修正に多くの時間をかけることとなってしまいました。

その時に使った解決方法について多くの方に周知させていただければと思い、筆を執らせていただきました。

目次

解決方法

結論から先に申し上げると、実装したい機能を細分化してJavaで行うものとJavaScriptで行うものに明確に分け、それぞれで独立した処理を行うことで解決しました。

以前はJavaとJavaScriptの担当する箇所が混然となっていましたが、一度機能を細分化することで「Javaが担当する箇所」と「JavaScriptが担当する箇所」に担当箇所の分担が可能になりました。

そうしたことで混同は解決され、機能についても思った通りのものを実装することができました。

作業環境

  • Eclipse:Photon Release (4.8.0)
  • Java:java8
  • Tomcat:バージョン8.x

何を行いたかったのか

説明を単純化するために、以下のような仕様のWebアプリを作りたかったと仮定します。

  • チャットの履歴を10件ずつ区切っておく
  • 区切ったチャットの背景色をそれぞれ違う色で塗りつぶす

起こったことと解決方法の詳細、所感

起こったこと

Webアプリの作成のために、JSP内に以下のようなコーディングを行いました。

<%@ page import="dto.TestDto"%>
<%@ page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>
    </head>
    <body>
        <% ArrayList<TestDto> testList = (ArrayList<TestDto>)request.getAttribute("testList"); %>

        <% // データベースから取得したデータをHTMLの構文に生成する処理 %>
        <% // 区切った位置を記録する配列の宣言 %>
        <% ArrayList<Integer> numList = new ArrayList<>(); %>
        <% for (int i = 0; i < testList.size() ; i++) { %>
            <% TestDto test = testList.get(i); %>

            <% // リストを10個ずつに区切る処理 %>
            <% if (i % 10 == 0) { %>
                <% // 区切った位置をリストに記録する %>
                <% numList.add(i / 10); %>
                <div id="<%= i %>">
            <% } %>

            <p><%= test.getId() %><%= test.getContent() %></p>

            <% if ((i + 1) % 10 == 0) { %>
                </div>
            <% } %>
        <% } %>
    </body>
    <script type="text/javascript">

       <% // 10個ずつに区切ったリストをそれぞれ色分けする処理 %>
       for (let i = 0; i < <%= numList.size() %>; i++){
           if (<%= numList.get( %>i<%= ) %> % 2 === 0){
               document.getElementById("<%= numList.get( %>i<%= ) %>").style.backgroundColor = "#ff7f50";
           } else {
               document.getElementById("<%= numList.get( %>i<%= ) %>").style.backgroundColor = "#b0c4de";
           }
       }
   </script>
</html>

その結果として様々なエラーが発生し、実行することができませんでした。

こうしたことの他にもJavaとJavaScriptを組み合わせる試行錯誤の結果として様々なエラーが発生し、プログラムを正常に動かすことができなくなっていました。

解決方法の詳細

こうした事態の根本的な解決をするために、冒頭でも述べたように私は実装したい機能を細分化してJavaで行うものとJavaScriptで行うものに明確に分け、それぞれで独立した処理を行うようにしました。

以前は機能の分担についてあまり考えずに、JSPファイル内ですべての処理を完結することを意識してコーディングを行っていました。そうした結果、

  • JavaとJavaScriptの担当する箇所が混然となってしまう
  • エラーによってプログラムが正常に動かなくなってしまう
  • 一目で何を行っているのかがわからなくなってしまう

という問題点が発生してしまいました。

そこで機能を

 機能1. Servletからのチャットデータの受け取り

 機能2. チャットデータをHTMLの構文に成形

 機能3. HTMLタグへのid属性付与

 機能4. 組み立てられたチャットデータのJSPへの貼り付け

 機能5. CSSの操作

といったように細分化することで、「Javaのmodelクラスが担当する箇所」と「JavaScriptが担当する箇所」に担当箇所の分担が可能になりました。

具体的には、以下のようにコーディングを行い、機能の分散を実現しました。

Javaのmodelクラス

package model;

import java.util.ArrayList;

import dto.TestDto;

public class TestHTML {
    // HTMLの構文に成形したリストを入れるフィールド変数を宣言する
    public String listHTML = "";

    // リストのHTMLの構文への成形をServletで行うようにした
    // 機能1・2の実装
    public TestHTML(ArrayList<TestDto> testList) {
        for (int i = 0; i < testList.size() ; i++) {
            TestDto test = testList.get(i);

            // リストを10個ずつに区切る処理
            // 機能3の実装
            if (i % 10 == 0) {
                listHTML += "<div id='" + i / 10 + "'>";
            }

            listHTML += "<p>" + test.getId() + ":" + test.getContent() + "</p>\n";

            if ((i + 1) % 10 == 0) {
                listHTML += "</div>";
            }
        }
    }

    // 成形したリストを返すメソッド
    public String getListHTML() {
        return listHTML;
    }
}

JSPファイル

<%@ page import="dto.TestDto"%>
<%@ page import="java.util.ArrayList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>
    </head>
    <body>

        <% // modelクラスで作成したリストを貼り付ける %>
        <% // 機能4の実装 %>
        <%= (String)request.getAttribute("testList") %>

    </body>
    <script type="text/javascript">

       <% // 区切った位置の記録をJavaScript上で行うようにした %>
       let numList = [];
       for (let i = 0; i < <%= (int)request.getAttribute("testListSize") %> ; i++) {
           if (i % 10 === 0) {
               numList.push(i / 10);
           }
       }

       <% // 10個ずつに区切ったリストをそれぞれ色分けする処理 %>
       <% // 機能5の実装 %>
       for (let i = 0; i < numList.length; i++){
           console.log(numList[i]);
           if (numList[i] % 2 === 0){
               document.getElementById(numList[i]).style.backgroundColor = "#ff7f50";
           } else {
               document.getElementById(numList[i]).style.backgroundColor = "#b0c4de";
           }
       }
   </script>
</html>

実行後の画面
実行後の画面

これによって上記の問題点は解決され、機能についても思った通りのものを実装することができました。

所感

この件を通して、私は

  • 集中しているときは視野が狭くなり、思考が固まりやすくなってしまうということ
  • 機能は一つのファイルに集約するのではなく、細分化したうえでそれぞれを異なるファイルで分担し合って処理を行わせた方が良いということ

といったことに気づかされました。

また、記事を書くにあたってコード自体についても先輩社員の方に見ていただいたのですが、

  • サーバサイドとフロントサイドが密接にかかわってしまっていると、開発や保守の観点から見て懸念点がある
  • システム開発は開発業務だけでなく設計とテストの工程も存在しているため、それを意識することでもっとよいコーディングを行うことができる

とアドバイスをいただきました。次からはいただいたアドバイスを基に、設計とテストの工程を意識した開発を行っていきます。

最後に、この記事が多くの人の役に立つことを願って筆を置かせていただきます。ご覧いただきありがとうございました。