sironekotoroの日記

Perl と Mac の初心者の備忘録

Mouseのコンストラクタで1時間ちょっとハマったところ

出オチ感がるんですが、こんなコードです。

Mouse を使った Perlオブジェクト指向のコードです。

意図したことは、$obj = UserID->new() でコンストラクタを呼ぶも、 required => 1 つまりオブジェクト生成時にプロパティを必須にしているのでエラーが出る・・・というものです。

#!/usr/bin/env perl
package UserID {
    use Mouse;

    has user_id => (
        is  => "rw",
        isa => "Str",
        default  => "",
        required => 1,
    );

    __PACKAGE__->meta->make_immutable();
}

package main;
use strict;
use warnings;

my $obj = UserID->new();

が、エラー出ません。

Google 翻訳片手にオフィシャルのページ読んでみたりしたのですが、解決せず。

metacpan.org

で、原因なんですが、ここです。

        default  => "",
        required => 1,

ここで、required => 1 としてオブジェクト生成時にプロパティを要求する・・・のと同時に、 default => "", と、何も指定されなかったときにデフォルト値が入る設定にしていました。

ということで、当初の意図通りオブジェクト生成時にプロパティを要求したいときには default => "", の行を消せば ok です。

マザーテレサの(ものとして流布されている)言葉をPerlで

うちのTLに流れてきたツイート

これはマザーテレサの言葉とされる文字列を表示する rubyスクリプトです。

ところで、本当にマザー・テレサの言葉かというとどうもそうではないというお話。

blog.blueeli.jp

さて、このスクリプトを動かすと、こうなります。

20-09-08 15:02:50 ~
$ ruby -e 'puts %w[思考 言葉 行動 習慣 性格 運命].each_cons(2).map { |a, b| "#{a}に気をつけなさい。それはいつか#{b}になるから。" }'
思考に気をつけなさい。それはいつか言葉になるから。
言葉に気をつけなさい。それはいつか行動になるから。
行動に気をつけなさい。それはいつか習慣になるから。
習慣に気をつけなさい。それはいつか性格になるから。
性格に気をつけなさい。それはいつか運命になるから。

左から右へ、メソッドチェーンで書かれていて面白いですね。

each_cons() ?

ruby がわからないうちでも、配列的なところから要素を2つずつ選んで、1つずつずらしながら表示している、というのはわかります。。

こういうの見ると、 Perl ではどう書くんかな〜って思いますよね?

・・・each_cons って関数がまず Perl にないっすね。

Perl each_cons でググります。

そのまんまの名前がついた List::EachCons モジュールを発見。

あるもんだなぁ。

いつも通り cpanm List::EachCons でインストール。そして、SYNOPSYSをちょこっと変えて動かしてみます。

metacpan.org

use List::EachCons;
my @list = qw/思考 言葉 行動 習慣 性格 運命/;
each_cons 2, @list, sub {

    print
        "$_[0]に気をつけなさい。それはいつか$_[1]になるから。\n";

};

うまく動きます。

モジュール使わないと・・・?

さて、モジュール使わない場合はどうなるんでしょう?

Perlでは、配列から複数の要素を取得できるスライスという機能があります。

my @list = qw/思考 言葉 行動 習慣 性格 運命/;

print @list[0,1] . "\n"; # 思考言葉

例では、配列 @list の 0番目と 1番目を print しています。

複数の値が返り値になるので、シジルが @ であることに注意です。

これを使って、2 つずつ配列から取り出してみます。

my @list = qw/思考 言葉 行動 習慣 性格 運命/;

print @list[0,1] . "\n"; # 思考言葉
print @list[1,2] . "\n"; # 言葉行動
print @list[2,3] . "\n"; # 行動習慣
print @list[3,4] . "\n"; # 習慣性格
print @list[4,5] . "\n"; # 性格運命

それっぽくなりましたね。

そして、このスライスのところに規則性が見えますね・・・ [0,1], [1,2], [2,3], [3,4], [4,5]

ここもわざわざ直接入力しなくても良さそうではありませんか?

ってことで、書いてみました。

scalar @list と書くことで、配列 @list の要素数が返ります。

my @list = qw/思考 言葉 行動 習慣 性格 運命/;

for my $index ( 0 .. scalar @list ) {
    last if $index == $#list; # 6番目の要素「運命」にきたら、そのペアとなる次の単語がないのでループを抜ける

    print
        "$list[$index]に気をつけなさい。それはいつか$list[$index+1]になるから。\n";
}

同じように表示できました。

めでたしめでたし。

Perlモジュール作成実況中継 一気通貫 テストを添えて

Perl でモジュール作るなら minilla がおすすめ(というかそれしか知らない)

Perl でモジュールを作るときは Minilla を使っています。

きっかけは Web+DB Press に掲載されて記事でした。

gihyo.jp

体系だった記事があると大変助かります。

$ cpanm Minilla でインストール後、早速モジュール作ります。

作るのは Acme::MetaVar というモジュール。

このモジュールは use Acme::MetaVar すると、hoge というメソッドを呼び出して使うことができる・・・とします。

利用イメージとしてはこんな感じ。

#!/usr/bin/env perl
use strict;
use warnings;

use Acme::MetaVar;

my $am = Acme::MetaVar->new();
print $am->hoge() . "\n";   # hoge

minil の使い方については記事を見てもらうとして、こんな感じで進んでいきます。

$ minil new Acme::MetaVar
(中略)
Finished to create Acme::MetaVar

これで雛形が出来上がったので、早速モジュール本体を作っていきます・・・の前に、git でコミットしておきます。

$ cd Acme-MetaVar/
$ git add .
$ git commit -m "initial commit"
[master (root-commit) 8704b2c] initial commit
 11 files changed, 585 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 .travis.yml
 create mode 100644 Build.PL
 create mode 100644 Changes
 create mode 100644 LICENSE
 create mode 100644 META.json
 create mode 100644 README.md
 create mode 100644 cpanfile
 create mode 100644 lib/Acme/MetaVar.pm
 create mode 100644 minil.toml
 create mode 100644 t/00_compile.t

ここまでの進捗です。

github.com

いざモジュール作成

モジュール作成に着手します。

$ cd Acme-MetaVar/
$ vim lib/Acme/MetaVar.pm

雛形のコードにサブルーチン9行足しただけですが、コードを載せておきます。

package Acme::MetaVar;
use 5.008001;
use strict;
use warnings;

our $VERSION = "0.01";

sub new {
    my $class = shift;
    my $self = bless {}, $class;
    return $self;
}

sub hoge {
    return "hoge";
}

1;
__END__
(中略)

さて、出来上がったら -c オプションつけてまずは文法チェックしてみます。

$ perl -c lib/Acme/MetaVar.pm
lib/Acme/MetaVar.pm syntax OK

問題ないっすね。

ここまでの進捗です

github.com

テストしてみる

ここで、Minilla が用意した雛形のテストを実行します。モジュールが use できるかどうか?というテストです。

テストには Perl と一緒にインストールされる prove コマンドを用います。

この provet/ ディレクトリ内のテストスクリプトを連続で実行してくれます。

実行場所は t/ ディレクトリと同じ階層になるので注意。t/ ディレクトリの中ではないです。

引数の -lハイフン エル を忘れずに。

$ prove -l
t/00_compile.t .. ok
All tests successful.
Files=1, Tests=1,  1 wallclock secs ( 0.04 usr  0.01 sys +  0.14 cusr  0.03 csys =  0.22 CPU)
Result: PASS

Result: PASS 、最高ですね。テスト成功です。

-lハイフン エル オプションをつけないと、「Perlがモジュール見つけられないよ!」ってな警告と共にテストが失敗します。

Perl がモジュールを探す場所(パス)に Acme::MetaVar が入っていないので当然ですね。今作ってる最中でインストール前だし・・・

以下がテスト失敗時のメッセージです。

$ prove
t/00_compile.t .. 1/?
#   Failed test 'use Acme::MetaVar;'
#   at t/00_compile.t line 4.
#     Tried to use 'Acme::MetaVar'.
#     Error:  Can't locate Acme/MetaVar.pm in @INC (you may need to install the Acme::MetaVar module)
(中略・ここにPerlがモジュールを探したパスが列挙されている)
at t/00_compile.t line 4.
# BEGIN failed--compilation aborted at t/00_compile.t line 4.
# Looks like you failed 1 test of 1.
t/00_compile.t .. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/1 subtests

Test Summary Report
-------------------
t/00_compile.t (Wstat: 256 Tests: 1 Failed: 1)
  Failed test:  1
  Non-zero exit status: 1
Files=1, Tests=1,  1 wallclock secs ( 0.03 usr  0.01 sys +  0.14 cusr  0.04 csys =  0.22 CPU)
Result: FAIL

ではここで一旦 git add . して git commitです。

sironekotoro 20-09-06 14:38:39 ~/Dropbox/perl/temp/Acme-MetaVar  (master +)
$ git commit -m "add method  'new',  'hoge'"
[master 79c4048] add method  'new',  'hoge'
 1 file changed, 9 insertions(+), 1 deletion(-)

閑話休題、実行時のパスについて

さて、スクリプトから開発中のモジュールを use して使って試してみたいときにも、同様にパスが見つからないよ!ってな問題が発生します。

例えば、Acme-MetaVar/test.pl を作って use してみます。

$ touch test.pl

test.pl の中身です。use しただけ。

#!/usr/bin/env perl
use strict;
use warnings;

use Acme::MetaVar;

実行するとエラーが出ます。prove-l なしで実行した時と同じですね。

$ perl test.pl
Can't locate Acme/MetaVar.pm in @INC (you may need to install the Acme::MetaVar module)
(中略)
 at test.pl line 5.
BEGIN failed--compilation aborted at test.pl line 5.

ですので、モジュール作成中のテストスクリプト中では、モジュールの位置を明示してあげる必要があります。

この test.pl からみてモジュール Acme::MetaVar があるのは同じ階層にある ./lib 以下です。ですので、このように1行追加します。

#!/usr/bin/env perl
use strict;
use warnings;

use lib ('./lib');

use Acme::MetaVar;

これでスクリプトを実行してもエラーが出なくなりました。

$ perl test.pl

テスト用のスクリプトを別の階層に書く場合は、相対パスにしろ絶対パスにしろ、モジュールがある場所を指定する必要があります。

テストを追加する

では、引き続きテストスクリプトを書いていきます。

#!/usr/bin/env perl
use strict;
use warnings;

use lib ('./lib');

use Acme::MetaVar;

my $am = Acme::MetaVar->new();
print $am->hoge() . "\n";    # hoge

prove -l で確認、無事動いてるようです。

さて、テスト用のファイルなのですが、Minilla が作成する雛形にはテスト用のスクリプト置き場があります。

t/ ディレクトリです。

ここにテストスクリプトをおくことで、 prove -l した際に一緒にテストしてくれるようになります。

せっかくなので、ここで先ほどの hoge メソッドを呼び出すテストを書いてみましょう。

先に作成したテスト用スクリプトは削除しておきます。

$ rm test.pl

今回は hoge メソッドを読んだときにちゃんと hoge という文字列が返ってきたら正常稼働とします。

$ touch t/01_hoge.t
$ vim t/01_hoge.t
use strict;
use Test::More 0.98;

use Acme::MetaVar;

my $am = Acme::MetaVar->new();

ok( $am->hoge eq 'hoge' );

done_testing;

文字列の比較演算子 eq を用いて、メソッドの返り値が hoge であるかを確認しています。

テストについてはここをよく参考にしたりしています。

gihyo.jp

perl-users.jp

さて、 prove -l で確認します。

$ prove -l
t/00_compile.t .. ok
t/01_hoge.t ..... ok
All tests successful.
Files=2, Tests=2,  0 wallclock secs ( 0.04 usr  0.01 sys +  0.22 cusr  0.06 csys =  0.33 CPU)
Result: PASS

おおっ!気持ちいい〜!

このように、テストしたい対象やテストするべきことがはっきりしているとテストも書きやすいです。

そう、意外に自分が何を求めているのか、わからないことも結構あるんですよね・・・人生と同じで・・・

ではここでまたgit add . & git commit しておきます

$ git add t/01_hoge.t
$ git commit -m "add test hoge"
[master 8c0ef38] add test hoge
 1 file changed, 10 insertions(+)
 create mode 100644 t/01_hoge.t

github.com

メソッドを増やす!その前に

ここで、新たにメソッド fuga を追加することになりました。使用イメージはこんな感じ。

print $am->fuga() . "\n";    # fuga;

Acme::MetaVar にサブルーチン追加していけば良さそうですね。

しかし、この先も同じような追加改修が続くかも知れません。piyo , foo, bar, buz ...

見通しの良いスクリプトにするために、メソッドごとにファイルを分けて管理することにします。

まずは、Acme::MetaVar から hoge メソッドを分離します。

Acme/MetaVar.pm から hoge サブルーチンを削除して、 Acme::Hoge モジュールを use します。

package Acme::MetaVar;
use 5.008001;
use strict;
use warnings;

our $VERSION = "0.01";

use Acme::Hoge; # 追加

sub new {
    my $class = shift;
    my $self = bless {}, $class;
    return $self;
}

1;
__END__
(中略)

そして、新規に Acme::Hoge モジュールを作ります。MetaVar.pm と同じ階層。treeで見るとこんな感じ。

├── lib
│   └── Acme
│       ├── Hoge.pm
│       └── MetaVar.pm

hoge メソッドを他のモジュール(今回は Acme::MetaVar )経由で利用できるよう、エクスポートしています。

package Acme::Hoge;
use 5.008001;
use strict;
use warnings;

our $VERSION = "0.01";

use Exporter 'import'; # エクスポーター

our @EXPORT = qw/hoge/; # エクスポートするメソッド

sub hoge {
    return "hoge";
}

では、これで prove -l でテストします・・・大丈夫ですね。

ではここでまた git で保存しておきます。

$ git add .
$ git commit -m "Moved the hoge method to another file"
[master ea84d86] Moved the hoge method to another file
 2 files changed, 16 insertions(+), 4 deletions(-)
 create mode 100644 lib/Acme/Hoge.pm

メソッドを分離しました。

github.com

fuga メソッドを「テストファースト」で追加してみる

さて、直近の課題たる fuga メソッドの実装です。・・・せっかくなので「テストファースト」で書いてみます。

先にテストを書くことで、スクリプトに何を求めているのか?をはっきりさせる効果があります。

では、hoge メソッドと同じように、fuga メソッドのテストを書いてみましょう。

と言っても、hoge をコピーしてファイル名と中身をちょっと変えるだけです。

fuga メソッドのテストファイルは 02_fuga.t とします。

$ cp t/01_hoge.t t/02_fuga.t
$ vim t/02_fuga.t

02_fuga.tの中身です。

use strict;
use Test::More 0.98;

use Acme::MetaVar;

my $am = Acme::MetaVar->new();

ok( $am->fuga eq 'fuga' );

done_testing;

では、prove -l です。

$ prove -l
t/00_compile.t .. ok
t/01_hoge.t ..... ok
t/02_fuga.t ..... Can't locate object method "fuga" via package "Acme::MetaVar" at t/02_fuga.t line 8.
t/02_fuga.t ..... Dubious, test returned 255 (wstat 65280, 0xff00)
No subtests run

Test Summary Report
-------------------
t/02_fuga.t   (Wstat: 65280 Tests: 0 Failed: 0)
  Non-zero exit status: 255
  Parse errors: No plan found in TAP output
Files=3, Tests=2,  1 wallclock secs ( 0.04 usr  0.02 sys +  0.32 cusr  0.08 csys =  0.46 CPU)
Result: FAIL

はい失敗しました。まだ Acme::Fuga も作ってないし、 Acme::MetaVar 内で use Acme::Fuga; してないからですね。

分かっていればテスト失敗も怖く無い・・・プッチ神父に通じる精神ですね。

では作っていきます。

package Acme::MetaVar;
use 5.008001;
use strict;
use warnings;

our $VERSION = "0.01";

use Acme::Hoge;
use Acme::Fuga;

sub new {
    my $class = shift;
    my $self = bless {}, $class;
    return $self;
}


1;
__END__
(中略)
package Acme::Fuga;
use 5.008001;
use strict;
use warnings;

our $VERSION = "0.01";

# Exporterを継承
use Exporter 'import';

# エクスポートする関数を記述
our @EXPORT = qw/fuga/;

sub fuga {
    return "fuga";
}

さて、どうでしょうか?

$ prove -l
t/00_compile.t .. ok
t/01_hoge.t ..... ok
t/02_fuga.t ..... ok
All tests successful.
Files=3, Tests=3,  0 wallclock secs ( 0.05 usr  0.02 sys +  0.32 cusr  0.08 csys =  0.47 CPU)
Result: PASS

はい、テストに通りました。

$ git commit -m "add fuga method"
[master 1218746] add fuga method
 3 files changed, 25 insertions(+)
 create mode 100644 lib/Acme/Fuga.pm
 create mode 100644 t/02_fuga.t

fuga メソッドを追加しました。

github.com

こんな感じで作っていくんだけど・・・

さも間違わずに迷うことなく出来上がったように書いてますが、もちろんそんなことないです。

たくさんのエラーに塗れておりますし、git status で確認しながらの作業です。

今回の記事は、だいたい2年くらい前の自分向けの記事でした。

追記

use Acme::Hoge;
use Acme::Fuga;

ってところ、単に hoge, fuga メソッドを使えるようにしているだけなのですが、これって継承では?やりたかったのって継承では?ってことで use base しました。

github.com

さらに追記

base はもう10年も前に非推奨ですね・・・ってことで use parent に置き換え〜

gfx.hatenadiary.org

github.com

Perl から Slack の incoming-webhook 宛にメッセージを飛ばす

あっさりできてしまった。

#!/usr/bin/env perl
use strict;
use warnings;

use URI;
use HTTP::Tiny;
use JSON qw/encode_json/;

my $url = URI->new('slackのincoming-webhookのURL');

my $ht = HTTP::Tiny->new;

# リクエストに必要なHTTPヘッダーを組み立て
my $header = {
    headers => {
        'Content-Type'  => 'application/json; charset=utf-8',
    },
    content => encode_json {
            text => "test text",
    },
};

my $response = $ht->request( 'POST', $url, $header );

print "$response->{status} $response->{reason}\n";

f:id:sironekotoro:20200905132303p:plain

自作CLIアプリでもターミナルっぽいカーソル操作を行いたい!

自作CLIアプリでもターミナルっぽいカーソル操作を行いたい!

例えば、こんな感じの入力〜出力の簡単なスクリプトがあります。

#!/usr/bin/env perl
use strict;
use warnings;

while (1) {
    print "input>";
    my $input = <STDIN>;
    chomp $input;
    print $input . "\n";
}

入力して enter で確定すると、入力した文字列が出てくるようなのですね。Perl入学式の第2回でやるやつです。

で、ターミナルと同じようにカーソルキー(矢印キー)の上とかで過去の入力履歴を利用したいなー、と思って実際にカーソルキーを押すと・・・

f:id:sironekotoro:20200905100922p:plain

こんな感じになります。^[[A ってのはキーが押された時に実際に送信されるものです。

シェルである bashzsh はこれらを受け取って上に移動する、とか一つ前のコマンド履歴を出す、という動きに置き換えているわけです。

で、先の自作スクリプトでもターミナルと同じように過去のコマンド履歴を利用したいときはどうするか?ということで、今回は Term::ReadLine::Gnu を使ってみました。

metacpan.org

インストールはいつもの cpanm

$ cpanm Term::ReadLine::Gnu

こんな感じです。ほぼ、モジュールページの SYNOPSYS のまんまです。助かりますねー

#!/usr/bin/env perl
use strict;
use warnings;

use Term::ReadLine;    # Do not "use Term::ReadLine::Gnu;"
my $term = new Term::ReadLine 'ProgramName';
while ( defined( my $input = $term->readline('prompt>') ) ) {
    print $input . "\n";
}

f:id:sironekotoro:20200905102406p:plain

これで矢印キーを使って過去の入力履歴を利用することができるようになりました。

入力したものはちゃんと chomp もしてくれるようで何よりですね。

入力と出力が連続するようなアプリ、例えばファイルの検索を連続して行うとか、株価コードを入れてその予想株価を返すのを繰り返すとか、そういう自作アプリに使っています。

2020年のPerl入学式

さて、新型コロナウイルスの蔓延により中止となった第5回から半年・・・運営メンバーで再始動に向けて動いています。

遠くないうちにお知らせできると思うので、Perl触ってみたい!けどきっかけがなかった・・・という方はお楽しみに!

DDDをちょっとかじってみる

技術書を出版している翔泳社さんという出版社があり、たまに電子書籍のセールをやっています。

そこで、前から気になってはいたけどよく知らない、Webでさらっと見たけどとっつきにくそう、最近耳にした、ということでDDDの本を買ってみました。

www.shoeisha.co.jp

例示のコードはC#で、C#は名前しか知らないんですが・・・まぁ、なんとかなります。読むだけなら。

というかプログラム言語って「上から下に読む」「カッコの中はまとまりのある内容」「英語」という共通点があるので、なんとかなってる感です。

(たまに、それでなお読めない言語とかもあるけど)

Perlにはない仮引数とかも、JavaScriptで見たやつだなーとか、そんなレベルで見て写経しています。

ただ、言語の違いよりは「値オブジェクト」とかのDDD特有の概念を噛み砕いていくのが大変そうという感じです。

Kindle版で読んでいるので11%くらいの読破率なのですが。何度もスルメみたいに噛んで覚える本なのかもしれません。

#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;
use Data::Dumper;

my $name_a = FullName->new( "Larry", "Wall" );
say $name_a->last_name;    # Wall

my $name_b = FullName->new( "Anders", "Hejlsberg" );
say $name_b->last_name;    # Hejlsberg

# オブジェクトの属性を取り出しての比較。一見自然だが・・・
# FullNameオブジェクトが値であることを考えると不自然な記述
# この辺りはまだ納得がいっていない(「値である」のところ)
#
# ただ、後述の比較方法の方が「自然」というのはわかる。
if (   ( $name_a->last_name eq $name_b->last_name )
    && ( $name_a->first_name eq $name_b->first_name ) )
{
    say "equal";
}
else {
    say "not equal";
}

# 値オブジェクト同士を比較するメソッドを用意する方法(自然)
if ( $name_a->Equals($name_b) ) {
    say "equal";
}
else {
    say "not equal";
}

# 値オブジェクト同士の比較を、演算子オーバーライドを活用する(より自然)
if ( $name_a == $name_b ) {
    say "equal";
}
else {
    say "not equal";
}

package FullName;
use overload '==' => "Equals";

sub new {
    my $class = shift;
    my ( $first, $last ) = @_;
    my $self = bless { first_name => $first, last_name => $last }, $class;
    return $self;
}

sub last_name {
    my $self = shift;
    return $self->{last_name};
}

sub first_name {
    my $self = shift;
    return $self->{first_name};
}

sub Equals {
    my $self  = shift;
    my $other = shift;

    if (   $self->first_name eq $other->first_name
        && $self->last_name eq $other->last_name )
    {
        return 1;
    }
    else {
        return 0;
    }

}

GASでジャパンネット銀行の振込み手数料判定カスタム関数を作った

ネタがどんどん経理に傾いてきてますが、そういう時期なんですね。

さて、ジャパンネット銀行という銀行があります。2000年に開業した日本初のネット専業銀行です。

法人口座の手数料は以下となっています。

www.japannetbank.co.jp

  • ジャパンネット銀行の口座宛であれば金額にかかわらず55円

  • 他行の口座宛であれば、30,000円未満は176円、30,000円以上だと275円

これを Google Apps Script でカスタム関数にしてみました。

カスタム関数

カスタム関数とは、こういうものです。

例えば、2つのセルの合計を求める時には sum 関数というものを使います。

=sum(A1, A2)

この sum のような関数を自分で作ることができるのが Google Apps Script のカスタム関数です。

tonari-it.com

ジャパンネット銀行手数料関数

ジャパンネット銀行の手数料を計算する時、判定の材料は2つです

Perlだったら、引数を2つ取るサブルーチンにしてこんな感じにしますかねー

sub japannet_fee {
    my ( $bank, $remittance ) = @_;
    if ( $bank eq 'japannet' ) {
        return 55;
    }

    if ( $remittance < 30000 ) {
        return 176;
    }
    else {
        return 275;
    }
}

では、これをそのままカスタム関数にしてみます。

Google Apps Script はJavaScriptなので・・・と言ってもあまりPerlと変わらないっすね。

function japanNetBankFee(bankName, num) {
  let fee = 0;

  if (bankName === "ジャパンネット") {
    return 55;
  }

  if (num < 30000) {
    fee = 176;
  } else {
    fee = 275;
  }

  return fee;
}

ちょっと手直し

コード中に直接、振込み手数料の金額を書いています。

このような数字はマジックナンバーと呼ばれ、避けるべきものとして知られています。

ja.wikipedia.org

というわけで、定数に置き換えていきましょう。ついでに、ドキュメンテーションコメントも追加します。

/**
 * ジャパンネット銀行の手数料(同行宛:55円, 他行宛:30000円未満176円、30000円以上275円)
 *
 * @param {string} 銀行名
 * @param {num} 振込額
 * @return {num} 振込手数料
 * @customfunction
 */
function japanNetBankFeeV2(bankName, num) {
  const FeesBetweenJNB = 55;
  const FeeOfLessThan30000 = 176;
  const FeeOf30000OrMore = 275;

  let fee = 0;

  if (bankName === "ジャパンネット") {
    return FeesBetweenJNB;
  }

  if (num < 30000) {
    fee = FeeOfLessThan30000;
  } else {
    fee = FeeOf30000OrMore;
  }

  return fee;
}

さらに、この関数は2つの仕事を持っているのでそれを切り出して・・・って程でもないので、今回はここまで!とします。

f:id:sironekotoro:20200807174818p:plain

f:id:sironekotoro:20200807174921p:plain

補足

来年にはペイペイ銀行になるそうな

nlab.itmedia.co.jp