品質向上WG LT: テーマ:「私が感動した/目から鱗だったコードとレビュー」

 

コメントの美

 

2018.9.18 Yasuharu SEKI

Love comment!!

yseki方針

コメントのないコードは

価値がない!

コメントの効用

コードの理解!

設計を見やすく!

構造を見やすく!

体裁を見やすく!

設計を見やすく!

構造を見やすく!

体裁を見やすく!

いわゆるコメント

まともなプログラマなら

みんな書く

設計を見やすく!

構造をみやすく!

体裁を見やすく!

空白・改行

インデント

var self = this;
self._promptPluginName()
    .then(
        function () {
            return self._promptDomainName();
        })
    .then(
        function () {
            return self._promptPluginID();
        })
    .then(
        function () {
            return self._promptPluginVersion();
        })
    .then(
        function () {
            return self._promptPluginPlatforms();
        })
    .then(
        function () {
            // remaining adjustments
            self.props.testbedName = self.props.pluginName + '_TestBed';
            self.props.testbedID = self.props.pluginID + '-testbed';
            self.props.TEST_FRAMEWORK = TEST_FRAMEWORK;

            done();
        });

JavaScript 標準的なインデント

    var self = this;
    self._promptPluginName()
    .then( function(){ return self._promptDomainName();      } )
    .then( function(){ return self._promptPluginID();        } )
    .then( function(){ return self._promptPluginVersion();   } )
    .then( function(){ return self._promptPluginPlatforms(); } )
    .then( function(){
      // remaining adjustments
      self.props.testbedName    = self.props.pluginName + '_TestBed';
      self.props.testbedID      = self.props.pluginID   + '-testbed';
      self.props.TEST_FRAMEWORK = TEST_FRAMEWORK;      
      
      done();
    });   

個人的こだわり

連続した同様のコードは1行に抑えて縦位置を揃える

  • コード間の違いを理解しやすくなる
  • typo に気づきやすくなる

設計を見やすく!

構造を見やすく!

体裁を見やすく!

セパレータ

  • CONFIG 部分とか

  • class の始めとか

  • member の定義部分とか

  • method の種類の切れ目とか

import * as React from 'react';

// ============================================================================
// CONFIG
//
 /* snip */

// ============================================================================
// Type definition
//
interface IProps {}
interface IStates {}

// ============================================================================
// Class implementation
//
export class SampleClass extends React.Component<IProps, IStates> {
  constructor(props) { super(props); }

  // --------------------------------------------------------------------------
  // render
  //
  render() {
    return (
      <div>
        {this.renderObject1()}
        {this.renderObject2()}
      </div>
    );
  }

  renderObject1() {
    return <div onClick={() => {this.handleSample1()}}>Object1</div>
  }
  renderObject2() {
    return <div onClick={() => {this.handleSample2()}}>Object2</div>
  }

  // --------------------------------------------------------------------------
  // UI action handling
  //
  handleSample1() {
    console.log('click object1');
  }

  handleSample2() {
    console.log('click object2');    
  }
}

export default SampleClass;
  • 意味の切れ目とか

  // --------------------------------------------------------------------------
  // オブジェクト位置
  //
  setLeft   ( left    : number ) { this.left    = left;   }  
  setTop    ( top     : number ) { this.top     = top;    }
  setWidth  ( width   : number ) { this.width   = width;  }
  setHeight ( height  : number ) { this.height  = height; }

  // --------------------------------------------------------------------------
  // オブジェクトのスタイル
  //
  setContent  ( content : JSX.Element ) { this.content  = content;  }
  setColor    ( color   : string      ) { this.color    = color;    }

  // --------------------------------------------------------------------------
  // 移動やアニメーション
  //
  moveTo  ( left: number, top: number, duration_ms: number) {
    // ... 移動のコード
  }
  changeColor ( newColor: string, duration_ms: number ) {
    // ... 徐々に色を変えるコード
  }

 プログラマーが「意味が変わる」と思ったところを伝える

  • まとまりで分ける
  • 参照や編集だけの関数と操作の関数で分ける
  • 操作対象で分ける
  • etc. etc.

// ============================================================================
// クラスの定義開始とか
// ============================================================================

// ============================================================================
// 関数群のセクション開始とか
// ----------------------------------------------------------------------------

// ============================================================================
// コンフィグなどの表題とか
// 

// ----------------------------------------------------------------------------
// 関数の開始部とか
// 

// 関数内でのコメントとか

Tips: セパレータの意味の強さで表現を変えてる

Tips: 右の終端は 80 文字目にしてる

意図が切り替わる

タイミングが

伝わると

読みやすくなる

と信じてる

コードの美しさ

どの程度の量

コメント

書いたらいい?

個人的意見

黄金比

1:1.618

3.82:6.18

yseki が書いたコードの例

generator-cordova-plugin-devbed / _plugin_platform /index.js

'use strict';
var assert = require('assert');
var yeoman = require('yeoman-generator');
var cordova_lib = require('cordova-lib');
var plugman = cordova_lib.plugman;

//============================================================================
// Yeoman generator implementation
//
module.exports = yeoman.generators.Base.extend({

  constructor: function (args, options, config) {
    yeoman.generators.Base.apply(this, arguments);
    this.props = options;
  },

  //==========================================================================
  // Add platform into plugin
  //--------------------------------------------------------------------------
  /// CWD changed to plugin directory
  ///
  plugin_changedir: function() {
    assert(this.props.pluginName,  'pluginName is required');
    process.chdir(this.props.pluginName);
  },
  
  //-------------------------------------------------------------------------
  // Run plugman: add platform
  //
  plugin_add_platforms: function() {
    this.log('*** Adding platform to plugin ***');
    
    var done = this.async();
    this._add_platforms(0, this.props.pluginPlatforms, done);
  },

  _add_platforms: function(idx, platforms, done) {

    if(platforms.length <= idx) {
      done();
      return;
    }
    
    var self = this;
    plugman.platform({ operation: 'add', platform_name: platforms[idx] }, function() {
      self._add_platforms(idx+1, platforms, done);
    });
  },

  plugin_back_to_root: function() {
    process.chdir('..');
  },
  
  // finalize this generator
  finalize: function() {
    if( this.props.done ){ this.props.done(); }  
  },  
  
});

コード行数:36

コメント性行数:23

3.9:6.1

ほぼ黄金比

やるな。俺。

我田引水

そんな私が

今までで最も

感動した

コード

H E L L O, W O R L D!

           main(l
      ,a,n,d)char**a;{
  for(d=atoi(a[1])/10*80-
 atoi(a[2])/5-596;n="@NKA\
CLCCGZAAQBEAADAFaISADJABBA^\
SNLGAQABDAXIMBAACTBATAHDBAN\
ZcEMMCCCCAAhEIJFAEAAABAfHJE\
TBdFLDAANEfDNBPHdBcBBBEA_AL\
 H E L L O,    W O R L D! "
   [l++-3];)for(;n-->64;)
      putchar(!d+++33^
           l&1);}

Result

出展

IOCCC

The International Obfuscated

C Code Contest

国際 読みにくい

C コード コンテスト

美しさと感動は

別物かもしれない...

終わりの言葉

考え抜かれた

コメントは

美しい

20180918 品質向上WG LT: 「コメントの美」

By Yasuharu Seki

20180918 品質向上WG LT: 「コメントの美」

  • 325