はじめまして、加藤です。本日よりチーム・タコブネとして「開発者ブログ」を作成することとなりました。
今回は仕事柄日々培ってきた『見やすいコーディング』について書いてみようと思います。
(※今回の記事内容は以前別ブログにて公開したものを移動させました)
前提条件として、開発ツールを使用することとします。「Eclipseを使うんだな」と考えて下さい。また、コーディングのレベルは技術者によって差が出てしまうので、読み手を設定しアウトプットの質をあわせることにします。読み手は「Java1年生、もしくは他言語をマスターしている技術者」です。それでは始めます。
(1)半角スペースを多用します
Object hoge = new Integer(100); Integer counter = (Integer)hoge;
例えばこのプログラムに、半角スペースを使うと、グッと読みやすくなります。
Object hoge = new Integer( 100 ); Integer counter = ( Integer ) hoge;
()の中に文字が存在する場合は、その前後に半角スペースを入れ、キャストする部分も半角スペースで間をとります。
checkData("123","345","abc");
checkDataという3つのパラメータを持つメソッドです。この場合はカンマに注目します。
checkData( "123", "345", "abc" );
カンマの後ろに半角スペースを入れることによって、一段と読みやすくなりますね。
たまに、こんなコードを見かけます。
checkData("123" ,"234" ,"abc");
とても読みやすいです。仮に「”234″」のパラメータのみをコメントアウトすることも可能なソースとなっています。
ですが、このような書き方をしているコードが大量にあるメソッドを想像してみてください。
大量にです……。
メソッドの流れを読むのに苦労しそうですよね。この記述はソースの可読性を極端に落としてしまうのです。読み手の手腕にもよりますが、今想定しているのはプログラム1年生か他言語の開発者なので、その視点で捉えて下さい。
次は1行が長い例を紹介します。また、「パラメータが多すぎるのは設計ミスだよ」という指摘は無しでお願いします。
SampleDTO sampleDto = (SampleDTO)testTableDAO.getPrimaryKey(dataDto.getId(),dataDto.getSubId(),dataDto.getStartDate(),dataDetailDto.getLineNo());
この長文について「1文が長過ぎるので読みやすくしてくれ」と言われた場合の、あまり好ましくない変更事例は以下になります。
SampleDTO sampleDto = (SampleDTO)testTableDAO.getPrimaryKey( dataDto.getId(), dataDto.getSubId(), dataDto.getStartDate(), dataDetailDto.getLineNo());
次も好ましくありません。変数を増やす事で、バグの温床を築いているようなものです。
String id = dataDto.getId(); String subId =dataDto.getSubId(); java.util.Date startDate =dataDto.getStartDate(); String lineNo =dataDetailDto.getLineNo(); SampleDTO sampleDto = (SampleDTO)testTableDAO.getPrimaryKey( id, subId, startDate, lineNo); // もしくは SampleDTO sampleDto = (SampleDTO)testTableDAO.getPrimaryKey(id,subId,startDate,lineNo);
プログラムの流れを考慮するなら、こう書くのが望ましいでしょう。
// ------------------------ // testTableからデータ取得 // ------------------------ SampleDTO sampleDto = ( SampleDTO ) testTableDAO.getPrimaryKey( dataDto.getId(),dataDto.getSubId(), dataDto.getStartDate(), dataDetailDto.getLineNo() );
極端に長い場合を除き、1列で記述できるものは半角スペースを利用して1列で記述します。またgetPrimaryKeyのパラメータが知りたい場合は、F2キーを押して、Eclipseの機能から参照して確かめます。このためにJavadocは必須です。
細かいパラメータを並べるのは、数行のプログラムならOKですが、実際にそのような機会はあまり無く、全体を流して読めるこの記述方法が重宝されるのです。
(2)括弧の始まりは改行しないほうが読みやすくなります
大規模開発をしていれば、今時そんなソース無いだろう……と思っていても、やはり先輩から教えられた作法を、ずっと教えられたまま使うプログラマは沢山いるものです。
if (test) { System.out.println("trueです"); }
これは
if ( test ) { System.out.println( "trueです" ); }
更に、
if ( true ) { System.out.println( "trueです" ); }
最後のは、「極端にIF文が短かった場合は、こういうのもアリ」という話です。通常は2番目のものを選択してください。
また、これがもう少し長い場合、僕はこうしています。
private static final String REQ_PARAM_TEST_ID = "testId"; private void getParam() { …… if ( request.getParameter( REQ_PARAM_TEST_ID ) != null && request.getParameter( REQ_PARAM_TEST_ID ).length() > 0 ) { // パラメータを設定する valueObj.setParam( request.getParameter( REQ_PARAM_TEST_ID )); } }
そう、IFの文の次に1行改行するのです。もちろんIFの始まりと終わったあとは1つ改行を入れます。これだけで相当読みやすくなります!
(3)IFとELSEIFにラベルコメントをつけましょう
基本的にコメントアウトは「//」しか使用しません。「/* */」の複数行コメントアウトは間違う恐れと、javadocコメントの「/** */」を間違って使用する開発者がいるからです。これを前提に、ラベルコメントを僕は3通り定義しています。
・処理の括りを説明するラベルコメント
// ----------------------- // USERテーブルに登録する // -----------------------
・上位処理の括りを説明するラベルコメント
// ================= // データを登録する // =================
・IF、ELSEIFなどに利用するラベルコメント
if ( hoge && hugo ) { // --- // hogeもhugoも正しい場合 // --- …… } else if ( hoge && ! hugo ) { // --- // hogeが正しいがhugoは正しくない場合 // --- …… } else { // --- // 上記以外 // --- …… }
(4)改行で処理に「固まり感」を持たせると流れを捉えやすくなります
これは(3)の「処理の括りを説明するラベルコメント」を利用するケースで、改行を入れて更に可読性を高める方法です。
// リクエスト情報からデータを取得します DataObject dataObj = getData( reequest ); // データの内容をチェックします boolean checker = isValidData( dataObj ); // 登録用にデータを編集します editData( dataObj ); // データを登録します if ( checker ) { try { // トランザクション開始 tran.start(); // コネクション取得 …… } catch ( Exception ex ) { // ログ出力 ex.printStackTrace(); // ロールバック rollback; } finally { // コミット commit; } }
これを、このようにします。
// --------------- // 登録データ準備 // --------------- // リクエスト情報からデータを取得します DataObject dataObj = getData( reequest ); // データの内容をチェックします boolean checker = isValidData( dataObj ); // 登録用にデータを編集します editData( dataObj ); // ----------- // データ登録 // ----------- // データを登録します if ( checker ) { try { // トランザクション開始 tran.start(); // コネクション取得 …… } catch ( Exception ex ) { // ログ出力 ex.printStackTrace(); // ロールバック rollback; } finally { // コミット commit; } }
まず、ある一定の処理に対して、「処理の括りを説明するラベルコメント」を最初に記述します。次に、ラベルの前に2、3行改行を入れて、それ以前の処理と切り離して下さい。処理の括りの最後も同様に2、3行改行します。これで相当処理の流れが読みやすくなったのがわかりますか?
(5)コメントを並べようとしてはいけません
綺麗なコードを書きたいがため、コメントを並べる人がいます。
String hoge = "111";// プリントアウトする文字列バッファ String id = "0";// プリントアウトする文字列の順番 boolean checkFlg = false;// 判定フラグ(初期値:プリントしない)
これはいけません。
// プリントアウトする文字列バッファ String hoge = "111"; // プリントアウトする文字列の順番 String id = "0"; // 判定フラグ(初期値:プリントしない) boolean checkFlg = false;
コメントを文の上に書いたり、後ろに書いたりと規則性が無いものは可読性に欠けます。落書きではないのだから、ルールを守って記述しましょう。
最後に
ここまで、プログラムにたくさんの「改行」「半角スペース」「ラベル付け」をしてコード量を増やしてきました。ですが実際には不要な改行を減らすことで、プラスマイナスゼロになっていることに気づきましたか?
プログラムはこのように「流れ」で捉えることを重要視して下さい。でないと、スパゲティのような、こんがらがった物が出来上がってしまいます。
ある現場で、別会社の女性先輩が後輩にこんなことを言っていました。
「プログラムは、美しくなくっちゃ!」
大変失礼ながら、この「美しい」発言をする人は括弧を改行したり、パラメータやコメントを一生懸命並べようとする癖があります。(ごめんなさい、ごめんなさい、僕の知る限りです)
良いんです、美しくなくても。
そのプログラムが、どこに使われるのかを意識して、そこに見合ったものを書くように心がけてください。それをする・しないで、品質に大きく差が出てきます。
一部、極端な例もありましたが、このような視点を入り口にアウトプットの質を高めるきっかけになればと思います。是非どれかひとつでも取り入れてみてください。
(katoh.yosuke.biz@gmail.com)@youfenam