swing、javaでタスク管理アプリを作る話

こんにちは、某社エンジニアです。
エンジニアなのにオブジェクト指向があいまいな理解しかできてないのはまずいと思い、勉強中です。
その一環として、タスク管理アプリを作りながらオブジェクト指向的な書き方を理解することにしました。
備忘録として過程を残していきます。

ひとまず仕様としてはこんな感じ。
・ 個人用のデスクトップアプリケーション（ログインとかそこらへんを入れる気はないです。）
・ 基本的なUIは`trello`をリスペクト　https://trello.com/
・ 登録されたタスクの記録は`SQLite`を使う

ということでトップページを作りました。
<img width="988" alt="スクリーンショット 2017-09-13 9.59.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/178311/04ba4d7f-13cd-a9ca-a744-40dbcf02eca6.png">

こんな感じのコードで動いてます。（リファクタリング前です。）

```
public class Top extends JFrame{
        /**
        * アプリケーションの起動
        */
        public static void main(String[] args) {
        	Top frame = new Top("Task Manager");
            frame.setVisible(true);
        }
        
        Top(String title){
        	setTitle(title);
            setBounds(100, 100, 1000, 800);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            setLayout(new FlowLayout());

            //TODOタスク表示領域
            //タスク表示領域配置
            JPanel TodoPanel = new JPanel();
            TodoPanel.setPreferredSize(new Dimension(300, 600));
            TodoPanel.setBackground(Color.WHITE);
            TodoPanel.setLayout(new BoxLayout(TodoPanel, BoxLayout.X_AXIS));
            
            //タイトルを置く用のパネル
            JPanel TodoTitlePanel = new JPanel();
            TodoTitlePanel.setPreferredSize(new Dimension(300, 60));
            TodoTitlePanel.setBackground(Color.WHITE);
            TodoTitlePanel.setLayout(new BoxLayout(TodoTitlePanel, BoxLayout.Y_AXIS));
            TodoTitlePanel.setAlignmentY(0.0f);
            TodoPanel.add(TodoTitlePanel);
            
            //タイトル配置
            JLabel label = new JLabel("TODO");
            label.setFont(new Font("ＭＳ ゴシック", Font.BOLD, 32));
            label.setAlignmentX(0.5f);
            TodoTitlePanel.add(label);
            
            //枠線
            LineBorder border = new LineBorder(Color.BLACK, 2, true);
            TodoPanel.setBorder(border);
            
            //DOINGタスク表示領域
            //タスク表示領域配置
            JPanel DoingPanel = new JPanel();
            DoingPanel.setPreferredSize(new Dimension(300, 600));
            DoingPanel.setBackground(Color.WHITE);
            DoingPanel.setLayout(new BoxLayout(DoingPanel, BoxLayout.X_AXIS));
            
            //タイトルを置く用のパネル
            JPanel DoingTitlePanel = new JPanel();
            DoingTitlePanel.setPreferredSize(new Dimension(300, 60));
            DoingTitlePanel.setBackground(Color.WHITE);
            DoingTitlePanel.setLayout(new BoxLayout(DoingTitlePanel, BoxLayout.Y_AXIS));
            DoingTitlePanel.setAlignmentY(0.0f);
            DoingPanel.add(DoingTitlePanel);
            
            //タイトル配置
            JLabel doingLabel = new JLabel("DOING");
            doingLabel.setFont(new Font("ＭＳ ゴシック", Font.BOLD, 32));
            doingLabel.setAlignmentX(0.5f);
            DoingTitlePanel.add(doingLabel);
            
            //枠線
            LineBorder border2 = new LineBorder(Color.BLACK, 2, true);
            DoingPanel.setBorder(border2);
            
            //DONEタスク表示領域
            //タスク表示領域配置
            JPanel DonePanel = new JPanel();
            DonePanel.setPreferredSize(new Dimension(300, 600));
            DonePanel.setBackground(Color.WHITE);
            DonePanel.setLayout(new BoxLayout(DonePanel, BoxLayout.X_AXIS));
            
            //タイトルを置く用のパネル
            JPanel DoneTitlePanel = new JPanel();
            DoneTitlePanel.setPreferredSize(new Dimension(300, 60));
            DoneTitlePanel.setBackground(Color.WHITE);
            DoneTitlePanel.setLayout(new BoxLayout(DoneTitlePanel, BoxLayout.Y_AXIS));
            DoneTitlePanel.setAlignmentY(0.0f);
            DonePanel.add(DoneTitlePanel);
            
            //枠線
            LineBorder border3 = new LineBorder(Color.BLACK, 2, true);
            DonePanel.setBorder(border3);
            
            //タイトル配置
            JLabel doneLabel = new JLabel("DONE");
            doneLabel.setFont(new Font("ＭＳ ゴシック", Font.BOLD, 32));
            doneLabel.setAlignmentX(0.5f);
            DoneTitlePanel.add(doneLabel);
            
            //ボタン配置
            JPanel buttonPanel = new JPanel();
            
            JButton createButton = new JButton("新規作成");
            createButton.setPreferredSize(new Dimension(100,50));
            buttonPanel.add(createButton);
            
            JButton editButton = new JButton("タスクを編集");
            editButton.setPreferredSize(new Dimension(100,50));
            buttonPanel.add(editButton);

            Container contentPane = getContentPane();
            contentPane.add(TodoPanel);
            contentPane.add(DoingPanel);
            contentPane.add(DonePanel);
            contentPane.add(buttonPanel);
          }
} 
```

まあ長いですね。
同じ処理をしている箇所が３つもあります。
swingでラベルをやパネルを作るときはいちいちnewしないといけないので面倒ですね。
ということで重複している処理をまとめたのが下記のコードです。

```
public class Top extends JFrame{
        /**
        * アプリケーションの起動
        */
        public static void main(String[] args) {
        	Top frame = new Top("Task Manager");
            frame.setVisible(true);
        }
        
        Top(String title){
        	setTitle(title);
            setBounds(100, 100, 1000, 800);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            setLayout(new FlowLayout());

            //TODOタスク表示
            makeTaskPanel("TODO");
            
            //DOINGタスク表示
            makeTaskPanel("DOING");
            
            //DONEタスク表示領域
            makeTaskPanel("DONE");
            
            //ボタン配置
            JPanel buttonPanel = new JPanel();
            TaskRegister taskRegisterPanel = new TaskRegister();
            this.add(taskRegisterPanel);
            taskRegisterPanel.setVisible(false);
            JButton createButton = new JButton("新規作成");
            
            buttonPanel.add(createButton);
            
            JButton editButton = new JButton("タスクを編集");
            editButton.setPreferredSize(new Dimension(100,50));
            buttonPanel.add(editButton);

            Container contentPane = getContentPane();
            contentPane.add(buttonPanel);
          }
        
        public void makeTaskPanel(String panelTitle){
        	//titleに指定したタイトルテキストをつけてタスクパネルを作ります
            JPanel mainPanel = new JPanel();
            JPanel titlePanel = new JPanel();
            JLabel titleLabel = new JLabel(panelTitle);
            LineBorder border = new LineBorder(Color.BLACK, 2, true);
            
        	//タスク表示領域配置
            mainPanel.setPreferredSize(new Dimension(300, 600));
            mainPanel.setBackground(Color.WHITE);
            mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS));
            
            //タイトルを置く用のパネル
            titlePanel.setPreferredSize(new Dimension(300, 60));
            titlePanel.setBackground(Color.WHITE);
            titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
            titlePanel.setAlignmentY(0.0f);
            mainPanel.add(titlePanel);
            
            //タイトル配置
            titleLabel.setFont(new Font("ＭＳ ゴシック", Font.BOLD, 32));
            titleLabel.setAlignmentX(0.5f);
            titlePanel.add(titleLabel);
            
            //枠線
            mainPanel.setBorder(border);
            
            Container contentPane = getContentPane();
            contentPane.add(mainPanel);
        }
} 
```

重複していたのは
１、必要なpanel, labelなどをnew
２、サイズとかをもろもろいじって配置
する部分だったのでそこの部分をメソッドに切り出しました。
オブジェクト指向では<strong> 凝集度は強く、結合度は低い</strong>ほど良い設計と言えるそうです。

重複した機能はできるだけまとめ、それを呼び出す側は簡単に呼び出せるようにする、ということですかね。
ということでこれからもガンガンやっていきます。