ソースコードを見やすくしよう!「リファクタリング」①

リファクタリング

今回はMQLの機能を利用するという事ではなく、ソースコード自体を整えて見やすくしていくリファクタリングの解説です。

ここではシストレファクトリーが開催しているプログラミング教室の、生徒さんのコードをお借りして改善してゆく試みです。

ソースコードの整理整頓『リファクタリング』

作成したソースコードを整えていくことを『リファクタリング』といいます。

リファクタリング・・・ソフトウェアの挙動を変えることなく内部構造を整理すること
(人間にとって読みやすくすること)

リファクタリングを一言で言うと↑上記の意味となります。

 

プログラムの挙動に問題がなくても無駄なコードがあったりわかりにくい構造だったりと、最適なコードとは限らないので、このようなコードを整理してゆく事を目的に行うのがリファクタリングです。

重複が多く無駄に複雑なコードにリファクタリングを行うと、

①バグが発生しやすく、バグの修正も困難なコードのリスクを解消
②他人はもちろん自分が見直す際の理解のし辛さを解消し、引継ぎなども容易に
③コードの理解が容易となり開発速度が向上し、修正や機能追加が円滑に

といったメリットがあります。

 

リファクタリング実践

それでは、コードを修正していきましょう。

こちらは『指定したローソク足がピンバーの時はtrueを、ピンバーでなかったらfalseを返す』関数です。

 

まずこちらの関数、『PinBar = true;』の部分についてですが、PinBarにtrueが入った後はPinBarの中身が再度Falseに変わることはありません。

この関数自体は判定を1回しか行わず、if文の結果でtrueかfalseを返すかが決まるので、以下のように書き換えることができます↓

 

続いて、この文はif文を使っていてelseも使うことができるので以下のように書き換えられます↓。

こうすることでPinBarを宣言している行がいらなくなります。

 

あわせてif文を整形して、最終的に以下のようなソースコードに修正できました↓。

 

最初と見比べてみると、とてもスッキリしています。

もちろんプログラムの挙動が変わってしまってはいけませんので、こまめに動作確認はおこなっておきましょう。

リファクタリングは小分けで修正作業をし、その都度こまめにコンパイル→テストを行う!

 

不要なif文に要注意! 深い入れ子は自分を苦しめる!

次は、決済をする部分のコードをリファクタリングしてみましょう。

if( OrdersTotal() > 0 ) {
   for( int i = OrdersTotal() - 1; i >= 0; i--) {
      if( OrderSelect ( i, SELECT_BY_POS )) {
//ロングの時、パーフェクトオーダー終了で決済する
         if( OrderType() == OP_BUY ) {
            if( PerfectOrderIncrease ( smashort, smamiddle, smalong ) == false ) {
               int result = OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), Slippage, clrRed );
               if(result < 0) {
                  Print("注文に失敗しました");
               } else {
                  bool orderSelectResult = OrderSelect (result, SELECT_BY_TICKET);
                  Print ("注文に成功しました。決済価格は " + (string)OrderClosePrice() + " です。");
               }
            }
//ショートの時、パーフェクトオーダー終了で決済する
         } else if (OrderType() == OP_SELL) {
            if( PerfectOrderFalling ( smashort, smamiddle, smalong ) == false ) {
               int result = OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(), Slippage, clrRed );
               if(result < 0) {
                  Print("注文に失敗しました");
               } else {
                  bool orderSelectResult = OrderSelect(result, SELECT_BY_TICKET);
                  Print("注文に成功しました。決済価格は " + (string)OrderClosePrice() + "です。");
               }
            }
         }
      }
   }
}

 

プログラミングスキルが高い人が見たら一目で無駄なところが多いと思うかもしれません。まず1行目と2行目に関してです。

1行目の『 if( OrdersTotal() > 0 )』は『1つでもエントリー状態であれば決済判定』という意味です。

2行目の『for( int i = OrdersTotal() – 1; i >= 0; i–)』は『 OrdersTotal() が0になるまでループし続ける』という意味で、つまり『 OrdersTotal() が0であれば実行されない』という意味です。

なので、1行目の『 if( OrdersTotal() > 0 ) 』は必要ありませんね。

 

続いて5,6行目です。

if( OrderType() == OP_BUY ) {
   if( PerfectOrderIncrease ( smashort, smamiddle, smalong ) == false ) {

↑この2行のコードなのですが、もしif文の形式が

 

if( 条件1 ) {
   if( 条件2 ) {

  }else{

  }
 }

↑このように分岐がありません。なのでif文の中にif文をつくる必要がなく

 

if( 条件1 && 条件2 ) {

 }

↑これでよいのでまとめます。

 

また、16,17行目の『//ショートの時、パーフェクトオーダー終了で決済する』の下にある

} else if (OrderType() == OP_SELL) {
   if( PerfectOrderFalling ( smashort, smamiddle, smalong ) == false ) {

↑こちらに関しても同じ内容なのでまとめておきます。

このようにif文の中にif文を入れることを『入れ子(英語ではネスト)』と言います。

入れ子のし過ぎはコードがとても見づらくなり、のちの自分をとても苦しめますので注意しましょう!

 

カオチャイ
カオチャイ
少し長くなりましたので、続きは「リファクタリング②」を御覧くださいね

 

作ったツールのコピーを防ぐ口座認証実装はこちらから
EAインジケーターに口座番号認証を実装
EAやインジケーターに口座縛りをつけてコピー対策【MQLAuth実装代行】 ※MQLAuth(エム・キュー・エル・オースと呼びます) MQLAuthのイメージ こちらは口座番号を登録するM...