ASとか

開発系の記事が多めです。タイトルのASはActionScriptの略です。

やったー!逆fizzbuzz書けたよー!\(^o^)/

fizzbuzz

逆FizzBuzz問題 (Inverse FizzBuzz) - 猫とC#について書くmatarilloの雑記
あるリストが与えられたときに、FizzBuzzを実行するとそのリストを出力するような最短の連続数列を求めよ。

魂のコード

package InverseFizzBuzz;

use strict;
use warnings;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(inverseFizzBuzz);

sub convert
{
    my $word = shift;
    
    if ("fizz" eq $word) {
        3;
    } elsif ("buzz" eq $word) {
        5;
    } elsif ("fizzbuzz" eq $word) {
        15;
    } else {
        undef;
    }
}

sub isMatchToAny
{
    my $n = shift;
    return ((0 == $n % 3) | (0 == $n % 5) | (0 == $n % 15));
}

sub isMatch
{
    my ($n, $m) = @_;

    if (0 == $n % 15) {
        undef;
    } elsif (0 == $n % $m) {
        1;
    } else {
        undef;
    }
}

sub matchList
{
    my ($init, $words, $result) = @_;

    my @dewords = @{$words};
    my @deresult = @{$result};

    my $match = &convert(shift(@dewords));

    for ($init..100) {
        push(@deresult, $_);
        if (&isMatch($_, $match)) {
            if (0 < scalar(@dewords)) {
                $match = &convert(shift(@dewords));
            } else {
                return @deresult;
            }
        } elsif (&isMatchToAny($_)) {
            last;
        }
    }
    undef;
}

sub inverseFizzBuzz
{
    my $match = &convert(shift);

    my @result;

    for (1..100) {
        if (&isMatch($_, $match)) {
            if (0 < scalar(@_)) {
                my @hiki = ($_);
                my @array = &matchList($_ + 1, \@_, \@hiki);

                if (!$array[0]) {
                    next;
                }

                if (!$result[0] | (scalar(@array) < scalar(@result))) {
                    @result = @array;
                }
            } else {
                push (@result, $_);
                last;
            }
        }
    }
    
    @result;
}

テスト

#!/usr/bin/perl

use strict;
use warnings;

use Test::Simple tests => 9;

use InverseFizzBuzz;

my @fizz = inverseFizzBuzz("fizz");
ok($fizz[0] == 3, 'fizz');

my @buzz = inverseFizzBuzz("buzz");
ok($buzz[0] == 5, "buzz");

my @fizzfizzbuzz = inverseFizzBuzz("fizz", "fizz", "buzz");
ok (join('.', @fizzfizzbuzz) eq "6.7.8.9.10", 'fizz fizz buzz');

my @fizzbuzz = inverseFizzBuzz("fizz", "buzz");
ok (join('.', @fizzbuzz) eq "9.10", 'fizz buzz');

my @buzzfizz = inverseFizzBuzz("buzz", "fizz");
ok (join('.', @buzzfizz) eq "5.6", 'buzz fizz');

my @fizzbuzzfizz = inverseFizzBuzz("fizz", "buzz", "fizz");
ok (join('.', @fizzbuzzfizz) eq "3.4.5.6", 'fizz buzz fizz');

my @fizzfizz = inverseFizzBuzz("fizz", "fizz");
ok (join('.', @fizzfizz) eq "6.7.8.9", 'fizz fizz');

my @buzzfizzbuzz = inverseFizzBuzz("buzz", "fizz", "buzz");
ok (!$buzzfizzbuzz[0], 'buzz fizz buzz #undef');

my @fizzbuzzbuzz = inverseFizzBuzz("fizz", "buzz", "buzz");
ok (!$fizzbuzzbuzz[0], 'fizz buzz buzz #undef');
$ perl InverseFizzBuzz.t 
1..9
ok 1 - fizz
ok 2 - buzz
ok 3 - fizz fizz buzz
ok 4 - fizz buzz
ok 5 - buzz fizz
ok 6 - fizz buzz fizz
ok 7 - fizz fizz
ok 8 - buzz fizz buzz \#undef
ok 9 - fizz buzz buzz \#undef

総評

______

←樹海

. ̄.|| ̄        ┗(^o^ )┓三
  ||           ┏┗   三
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄

苦にならないコードレビュー

はじめに

今お世話になってる現場で新規プロジェクトが始まりそうなのだが、このままだと再びコードレビュー無しの開発が始まってしまう気がしてならない。ただ、スケジュール的にキツそうな案件なので、最小の手間である程度の成果を得られる形式はなんだろうと考えてみた。

前に失敗したパターン

偉そうに言ってみたけど、実はコードレビューを上手くできたことはあまり無い。原因として

  • レビュアーがレビュー時に初めてコードを読む
    • 時間が掛かりすぎる。見てほしいポイントを伝えても、そもそもレビューイが見てもらうポイントを勘違いしてたら終わり
  • 細かく指摘しすぎる
    • 一歩踏み込むと宗教論争にまで行きそうなところまで突っ込む、そういう話は楽しいんだけど掛かる時間の割に成果が少ない
  • 量が多い
    • コード量が多いと、いろいろと突っ込みが入っても直すのがだるい。じゃあ次から気をつけますとかなっちゃう。
  • 基本はdis
    • ノウハウの共有のはずなのにdisばかりが多くて"良い箇所"の共有ができてなかった。あんまり言われると萎えるしね。

考えてみた

上の失敗例を踏まえつつ、普通のプログラマのためのコードレビュー方式を考えてみた。

事前にコードリーディングしてもらう

印刷したの渡してもいいし、リポジトリのコード読んでもらうでもいいんだけど、先に見てもらい、指摘ポイントをメモっておいてもらうのがいいのかなと。レビューがスムーズになるのは当然として

  • コードを読むスピードの差
  • 書いた人を目の前にして急いで読まなきゃいけないストレス

を解決できるのは大きい。

モラリストになりすぎない

突っ込みはある程度汎用的なところで止めること。限定的なケースでの突っ込みも重要なんだけど、長くならないようにしたい。最悪なのはレビュアーが指摘しまくる自分に気持ちよくなってるケース。相手のことを尊重しつつ、チームの底力を上がるための指摘をしたい。細かい話は昼飯のネタにして盛り上がりましょう。

ある程度小さい部分をレビューしてもらう

ここが難しいんだけど

  • あまりコード量が多くない
  • そのプロジェクトでよく書かれるであろうコードのエッセンスが多く含まれている

ところを選んでレビューしたい。
通信部分の基底クラスとそれを呼び出している所だとか、プロジェクトを通してよく書く例が良い。まず時間が節約できるし、みんなが関係する部分の方がレビューしたいと思うので。

likeを探す

この書き方イイネ!とか言われたい(俺が)、この書き方良いから全体で取り入れよう!とかなれば相当の収穫だと思ってる。あとdisるにしてもコードをdisるわけであってレビューイは一切disられてないことを意識しましょう。

おわりに

書いた部分は必ずレビューしてもらうって方式が前提ではないので、どちらかというと勉強会的な感じでやれればいいかなと思ってます。レビュアーがライブでリファクタリングするのとか最高。バグに関しては単体テストの意識合わせとかやった方が時間対効果高いんじゃないでしょうか。
さらにメンバー内でコード書くときの観点とかある程度共有しておけばよりスムーズに進むような気がする、自分の場合は

かなぁ。リファクタリング本とかも重要だとは思うけど、個人的には汚いコードはホコリみたいに積もるもの、最初にホコリを残す人間にならないことというモラルが一番だと思ってるので、リファクタリング技術は二の次のような気がします。*1

*1:ただしこういう意識を持った人間は必ず自分のコードに不満が出て勝手にリファクタリングの勉強すると思うけど

「ノンデザイナーズ・デザインブック」読了

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

ノンデザイナーズ・デザインブック [フルカラー新装増補版]

感想

作りたいWebアプリをスケッチすると必ずダサいものが出来るのですが、直し方がわからないので困っていました。で、twitterでたまに名前を見かけるこの本を読んでみたのですが、まさに

  • 小綺麗なプロトタイプを作りたいだけ
  • あまり勉強に時間をとられたくない

私のような人間にとっては(時間対効果的な意味で)ベストだったのかも知れません。
非常に読みやすい文調で、デザインの例となる絵が多く、本自体も薄いので思い出したくなったら会社を往復する電車内で復習できてしまうレベルです(一時間くらい)。マスターできるまで繰り返し読んでいこう。

リストと配列

基本

  • リスト
  • 配列
    • リストを格納する変数

配列へのアクセス

  • $hoge[0] = "hoge";
  • $hoge[n]と$hogeは別の名前空間に置かれる
  • 添字が配列の末尾より後ろを指した場合はundef
  • 配列の末尾より後ろに値をセットした場合、飛ばした中間の要素にはundefがセットされる
  • 最後の要素にアクセスするためには負数を使う
    • $hoge[-1]
    • これで末尾の一つ手前を取得できるけどあまりやりたくない($hoge[-2])

リストリテラル

  • (1, 2, 3)
  • ("hoge", 4.5)
  • ()
    • 空リスト
  • (1..100)
    • 100個の整数リスト

qwショートカット

  • qw(hoge fuga piyo)
    • 文字列のリストが作成できる
    • 各要素はシングルクォートで囲まれている扱いなので注意(\nとか)
  • 要素間の空白文字は捨てられるので、改行とか入れつつ読みやすくできる
  • qw後の()は別になんでもいい
    • qw{ }
    • qw/ /
    • qw! !
  • 要素内にこのデリミタを入れたい場合はエスケープする
    • qw( hoge\) fuga piyo )
    • qw! hoge\! fuga piyo !

リスト代入

  • リスト値を変数に代入
    • ($hoge, $fuga, $piyo) = ("hoge", "fuga", piyo);
    • 変数の数が余分にあればundefが代入され、リスト値が多ければ捨てられる
  • 関数の引数受け取りとか便利
    • my ($hoge, $fuga, $piyo) = @_;
  • 変数の値交換も便利

配列全体を表す@

  • @hoges = qw/ hoge hoge hoge /;
  • @words = (@hoges, fuga, piyo); #hogesは展開される
  • @empty = (); #@emptyをさらにリストに入れても無いのと同じ(undefが入ったりはしない)
  • @hoges = qw/ hoge undef hoge /; #明示的にundefを入れる

配列の先頭or末尾の要素を操作

  • 末尾の要素を取り除く
    • $fred = pop(@array);
  • 末尾に要素を追加
    • push(@array, 0);
  • 先頭の要素を取り除く
    • $m = shift @array;
  • 先頭に要素を追加
    • unshift(@array, 5);

配列を文字列に展開

  • スカラー変数と同じくダブルクォーテーション内で展開できる
    • "@array"
  • 文字列として@arrayを入れたい
    • "\@array"
    • '@array'

foreach

# 制御変数を明示的に指定
foreach $word (qw/ hoge fuga piyo /) {
    print "$word\n";
}

# デフォルト制御変数を使用
foreach (qw/ hoge fuga piyo /) {
    print "$_\n";
}

# 制御変数は値コピーではないので
# ループ中に対象のリストの中身を操作できる
@words = qw/ hoge fuga piyo /;
foreach (@words) {
    $_ .= "\n";
}

並び替え

# 逆順を取得
print reverse(1..10)."\n";

# デフォルトのソート(ASCIIコード順)
# ソート条件は他にも指定できる
@words = sort(qw/hoge fuga piyo/);
print "@words\n";

スカラーコンテキストとリストコンテキスト

  • 式が置かれている位置によって意味が変わる
  • コンテキスト == 式が置かれている場所を示す概念
  • Perlが式を解析する場合はスカラー値かリスト値のどちらかを期待する
    • 例外もある
  • コンテキストによって評価が変わる例
# リストの個数を返す
$n =  @array;
3 + @array;

# 文字列を逆順にして返す
reverse($hoge);
  • スカラーコンテキストを強制するscalar関数
    • リストコンテキスト強制関数は無い、必要ないとのこと
@array = qw/ a b c /;

# 配列の中身を表示する
print "string :", @array, "\n";

# 配列の要素数を表示する
print "number :", scalar @array, "\n";

リストコンテキストで

# 次の1行
$line = <STDIN>;

# 全ての行
@lines = <STDIN>;

# 全ての行を読み込み
# 各要素から改行を取り除く
chomp(@lines = <STDIN>);

interfaceのネスト

はじめに

サンドイッチメソッドを取り除こうとした時に、interfaceを使用するクラスにネストして書けるのか気になった。使用範囲的に別ファイルにするのも変な話だし

書けます

書けたのだが、他にもいろいろ書けるらしい。具体的には

  • interface内にネスト
  • interface内にネストしたクラスにネスト

とのこと。そもそもinterface内にクラスをネストできることを知らなかったので、ぜひ使っていきたいなと。
注意すべきところとしては、ネストしたinterfaceは修飾子があろうがなかろうがstaticになるというところ。アクセス制御は相応のものを指定すればOK。

public class My {
    private interface Foo {
        public void foo(Hoge hoge);
    }

    private void do (Foo f) {
        foreach (Hoge hoge : Hoges) {
            f.foo(hoge);
        }
    }

    private static void main(String[] args) {
        do(new Foo() {
            @Override
            public void foo(Hoge hoge) {
                // それぞれの処理
            }
        });
    }
}

さいごに

そもそもJava的にこの書き方はありなんだろうか。無名関数のようにインタフェースをポンポン作っていいのか不安。

@Overrideアノテーションでエラー

はじめに

既存のプロジェクトをインポートしたら@Overrideを使用している箇所でもの凄い怒られた。「型 ○○ のメソッド ×× はスーパークラスメソッドをオーバーライドする必要があります」って...してるじゃないかと

jdkのバージョンによって@Overrideアノテーションの仕様が違うらしい

調べてみたらこれがわかったので、プロジェクト設定からJavaコンパイラの項目を調べてみると、コンパイラー準拠レベルが1.5になっていました...これを1.6に変更、エラーが消えてくれました。Eclipseの設定としては1.6になってたので私は問題なかったですが、こちらも確認しておくとよいかなと

ちなみに

中には@Overrideを消すとかいうなんともいえない対応方法もネットに転がってたので気をつけたほうがいいですね

数値と文字列

浮動小数

  • Perlの内部での計算は倍精度浮動小数点数で行われる
  • つまり内部では整数値というものは無い
  • でも浮動小数点数用の演算子も整数用の演算子もあるよ
  • 10の何乗かを表すE記法(指数記法)を付けられる
    • 7.25e45(7.25かける10の45乗)
    • -6.5e24(マイナス6.5かける10の24乗)

整数

  • アンスコで繋げて読みやすく
    • 61_298_040_283_768

数値演算子

  • 剰余できます
    • 10 % 3 = 1
  • べき乗もできます
    • 2**3 = 8

文字列

  • シングルクォート文字列リテラル
    • シングルクォートと逆スラ(続けて置いた場合)以外のすべてを文字として認識する
    • 文字中にシングルクォートを入れたい場合は逆スラでエスケープ
    • 改行文字を入れたい場合は連結させるとか
  • ダブルクォート文字列リテラル
$hoge = "hoge";
print "string: $hoge\n";

@hogefuga = qw/hoge fuga/;
print "array1: @hogefuga\n";
print "array2: ".@hogefuga."\n";
perl test.pl
string: hoge
array1: hoge fuga
array2: 2
$s1 = "hoge" x 3;
print "repeat1: $s1\n";

$s2 = 5 x 4;
print "repeat2: $s2\n";
$ perl test.pl 
repeat1: hogehogehoge
repeat2: 5555

スカラー変数

  • 頭に$,変数宣言後も$はずっと付く
  • 比較演算子は数値と文字列で別に用意されている(eq, ne等)
    • 文字列は標準文字列ソート順で判定
  • ブール値
    • 0、空文字は偽
  • 未定義値はundef
    • 基本0または空文字列として振る舞う
    • 警告ONの場合はprintで表示しようとすると警告
    • defined関数で偽が返ればundef