yucatio@システムエンジニア

趣味で作ったものいろいろ

プログラミングで初学者のときにつまづいたこと

プログラミングでつまづいてきたことというブログ記事を見たので、私も書いてみます。

satoru-takeuchi.hatenablog.com

mizchi.hatenablog.com

自己紹介

記事をリンクしたお2人と違って大したプログラマではないですが、システムエンジニアとして働いて10年経ってみて今の仕事が向いていると思っているところです。

大学でC言語Javaを習って、仕事はWeb系で主にJavaを使用しています。

以下、つまづいたことです。だいたい古いのから新しいものになっています。

代入文

a = 1
b = 2
c = a + b

でcが3になるのは分かったのだが、

a = a + 1

これを見て、"左右が等しくない。"と混乱し、そこで思考が止まってしまった。 半年後くらいに代入文という言葉を覚え、上記は"a + 1を計算した結果をaに入れる"だということが分かった (が慣れるまでにはもう少しかかった)。

アルゴリズム

プログラムそれ自体よりもアルゴリズムでつまづく(大学の授業で習った。言語はC言語。)

バブルソートわからない。わかってもコードに落とし込めない。2重ループが難しすぎる。

こんなに便利な世の中なのに、並び替えをするのにいちいち自前でプログラミングをしなければいけないなんて、どうなっているのだと思った。 (色々と認識が間違っていた)

Java

オブジェクト、インスタンス、クラス

用語の説明を何度読んでも理解ができない。他にもとにかく馴染みのないカタカナ語が多すぎて嫌になった。

あるとき、C言語の構造体に関数を足したのがクラスだと気づきそこから理解が進んだ。が、C言語を習っていなかったらと思うと震える。

Javaオブジェクト指向 (継承、ポリモーフィズムカプセル化)

惑星クラスを拡張したのが、水星クラス、金星クラス、土星クラスとか、 犬クラスだったら"ワン"と鳴いて、猫クラスだったら"ミャー"と鳴くとか、何に使うかがわからなかった。 値の隠蔽(カプセル化)が重要という割に、setterで値を操作できているではないか、と思った。

理解できるようになったのは、Javaデザインパターンを読んでから。


ちなみに"オブジェクト指向とは何か"はこちらの記事でWindows95を開発した中島聡さんの言葉を引用しています。

yucatio.hatenablog.com

インターフェース

インターフェースも何に使うか長年の疑問だった。実装がないとは何の役にも立たないのではないか。

確かこの本だったと思うけど、"例えば、自動販売機、外側に見える部分がちゃんと仕様通りに動いていれば、中に人が入っていて、手でジュースを出してもよい。自動販売機の、外から見える部分がインターフェース、中の機械とかが実装"、といったことがイラスト付きで書いてあって、その図がシュールで印象に残った。この例からなんとなく理解し始めたように思う。


その後、"仕様と実装を分けて考える"ということができるようになってきたのでインターフェースの使い所もはっきりしてきた。

Rubyのmap関数

array.map {|i| i * 2 }

で、なぜ各配列の値が2倍されるのか分からなかった。Javaしかほぼやってこなかったので、変換後の配列が定義されていないことが不思議だった。

JavaのMapとRubyのmapは全くの別物ということに思い当たったのと(JavaのMapはRubyのhash)、 とりあえずJavaでの記法(for文を使うもの)と対比させて覚えた。

プログラミング以外でのつまづきも多い

リンク先での記事でも「オブジェクト」「スタック」「ヒープ」が多義語で分かりにくかったとの記載があったが、 自分の場合は「ドメイン」「インスタンス」が多義語で混乱した。がこれはプログラミングではないもの(プログラミングの周辺知識ではあるが)も含まれているので機会があれば書きたい。

最近はプログラミング言語それ自体というより、周辺のツールで使用される概念や用語の理解に苦労する。 最近だとDockerの用語の理解でつまづいた。

あとがき

書きながら、プログラム始めたばかりのころ 全然コードが動かなくて吐きそうになったのを思い出しました。

とりあえず私から言えることは、Javaは最初に学ぶような言語ではないということです。

eclipseのJavadocの警告設定の各設定値の意味【後編】

Javadocの記述が不完全なときに警告を出そうとして、どのような設定があるか調べたメモです。

チーム開発でJavadocをどの程度書くかどうか、意識を統一するのにこの記事をご活用いただければと思います。

前編の記事

yucatio.hatenablog.com

未指定の Javadoc タグ

"未指定の Javadoc タグ"をONにすると、メソッドに定義されていてJavadocに記載されていないパラメータや例外などがある場合に警告を出します。

f:id:yucatio:20200113175535p:plain

メンバーの可視性を次のように設定

設定した可視性以上のJavadocのみ、"未指定の Javadoc タグ"の警告を出します。

オーバーライドしたメソッドの実装を無視

Javaでは、オーバーライドしたメソッドのJavadocは、子クラスの内容で親クラスの内容を上書きした内容となります。 以下の例では、子クラスでdescriptionと変数xの記述を上書きし、他のparamとreturnについては、親クラスの記述が引き継がれています。

f:id:yucatio:20200113180300p:plain

"オーバーライドしたメソッドの実装を無視"をOFFにすると、オーバーライドしたメソッドであっても、未指定の Javadoc タグがある場合には警告を出します。

f:id:yucatio:20200113180008p:plain

ただし、@Overrideアノテーションが付いている場合、警告は出ません。

f:id:yucatio:20200113180021p:plain

詳しい仕様と仕様が策定された経緯につきましてはこちらをご覧ください。

6.15 complains about missing @return tag in a overridden method · Issue #2869 · checkstyle/checkstyle · GitHub

メソッド型パラメータを無視

メソッド型パラメータとは、 ジェネリックメソッドにおいて、メソッドの戻り値の型の直前に書かれた<T>などの型の仮型パラメータのことです。 (参考: Java ジェネリクス(クラス、メソッドを定義する) - Qiita )

"メソッド型パラメータを無視"がONのときは、この<T>のためのJavadoc(@param <T>)がなくても警告を出しません。

OFFにすると、警告を出します↓

f:id:yucatio:20200113195747p:plain

未指定の Javadoc コメント

"未指定の Javadoc コメント"をONにすると、Javadocが記載されていない場合に警告を出します。

"メンバーの可視性を次のように設定"を"Protected"にした時の表示です↓

f:id:yucatio:20200113215408p:plain

メンバーの可視性を次のように設定

設定した可視性以上のJavadocのみ、警告を出します。

オーバーライドしたメソッドの実装を無視

"オーバーライドしたメソッドの実装を無視"をONにすると、オーバーライドしたメソッドにJavadocが無くても警告を出しません。

オーバーライドしたメソッドは、Javaでは親クラスのJavadocが使用されるため、指定しなくても問題ないことが多いかもしれません。

"オーバーライドしたメソッドの実装を無視"をOFFにすると、オーバーライドしたメソッドにも警告を出します。

f:id:yucatio:20200113220027p:plain

"未指定の Javadoc タグ > オーバーライドしたメソッドの実装を無視" の設定とは違い、こちらは@Overrideアノテーションのあるなしでの挙動の違いはありません。

オーバーライドしたメソッドに親と同じ内容のJavadocを書ときは、{@inheritDoc}タグを使うと便利です。

  /**
   * {@inheritDoc}
   */
  @Override
  public int calcA(int x, int y, int z) {
    return x + y + z + 1;
  }

参考: オーバーライドしたメソッドのJavadoc - 気付いたとき、気が向いたとき。by ykhr

環境

あとがき

"未指定の Javadoc タグ > オーバーライドしたメソッドの実装を無視" の設定が自分の想定と違った動作をしたので意外と苦戦しました。

参考サイト

eclipseのJavadocの警告設定の各設定値の意味【前編】

Javadocの記述が不完全なときに警告を出そうとして、どのような設定があるか調べたメモです。

チーム開発で、Javadocをどの程度書くかどうか、意識を統一するのにこの記事をご活用いただければと思います。

Javadocの警告設定

Javadocの書き方がよくないときに警告を出す設定の場所は、 設定 > Java > コンパイラー > Javadoc です。

f:id:yucatio:20200112222657p:plain

Javadocコメントを処理

"Javadocコメントを処理"をONにすると、Javadocとメソッドが連携されます。 変数名を選択したときにJavadocのparamの変数名もハイライトされます。

ONのとき↓

f:id:yucatio:20200112223145p:plain

OFFのとき↓

f:id:yucatio:20200112223156p:plain

また、ONにすると、変数のリネーム時にJavadocのparamの変数も同時に変更されます。

ONのとき↓

f:id:yucatio:20200112223411p:plain

OFFのとき↓

f:id:yucatio:20200112223421p:plain

誤った形式の Javadoc コメント

"誤った形式の Javadoc コメント"をONにすると、波かっこが閉じていないときなどに警告を出します。

f:id:yucatio:20200112223630p:plain

メンバーの可視性を次のように設定

設定した可視性以上のJavadocのみ、警告を出します。

可視性をProtectedにしたときに、PublicとProtedtedメソッドのにのみ警告が出て、パッケージとPrivateのメソッドに警告は出ません↓(タグ引数の検証をONにしたときの警告)

f:id:yucatio:20200112224059p:plain

"タグ引数の検証"をONにすると、@param, @throws, @exceptions, @see, @linkに 指定されたクラスやメソッドが存在しないときに警告を出します。

min1という引数はメソッドに存在しないため、警告が出ます↓

f:id:yucatio:20200113142031p:plain

f:id:yucatio:20200113141532p:plain

Nowhere.nomthodという存在しないクラスとメソッドを参照しているので警告が出ます↓

f:id:yucatio:20200112224211p:plain

不可視参照をレポート

"不可視参照をレポート"をONにすると、 不可視なメソッドなどを参照をしたときに警告を出します。不可視な参照とは、例えば他のクラスのprivateなメソッドや定数です。

他のクラス(SamplePrivateクラス)のprivateな定数(DEFAULT_NAME)を参照しているので、警告が出ます↓

f:id:yucatio:20200112224444p:plain

使用すべきでない参照をレポート

"使用すべきでない参照をレポート"をONにすると、非推奨(Deprecated)となったメソッドや変数を参照したときに警告します。

f:id:yucatio:20200112224653p:plain

タグ記述の欠落

"タグ記述の欠落"の設定では、 @param 変数名@returnなどのタグのあとの記述が無いときに警告を出します。

@return タグの検証ではその名の通り、@returnタグの後に何も書かれていなければ警告を出します。その他のタグの後には何も書かれていなくても警告を出しません。

f:id:yucatio:20200112225611p:plain

全ての標準タグを検証にすると、全ての標準タグにおいて、タグの記述がない場合に警告を出します。標準タグとは javadoc - Java API ドキュメントジェネレータ に記載されているタグです。

f:id:yucatio:20200112225624p:plain

後編

長くなったので続きます。

yucatio.hatenablog.com

環境

参考サイト

eclipseの警告表示の重大度レベルごとの挙動

前回の記事で、eclipseの警告レベルをどれにするか迷ったので、各重大度レベルでの挙動を確認しました。

yucatio.hatenablog.com

eclipseの警告表示の設定

eclipseを使用していると、黄色の波線と警告マーク(3角形の中に!)が表示されたことがあるでしょう。 これらの設定は、 設定 > Java > コンパイラー > エラー/警告 で変更可能です。

f:id:yucatio:20200110081256p:plain

エラー、警告、情報、無視の違い

エラー/警告の設定では、eclipseが問題を検出したときにの重大度を設定できます。

重大度レベルごとのeclipseの挙動です。

重大度レベル 表示
エラー 問題がある箇所に赤の点線が引かれ、該当する行及びファイル名にバツ(×)印がつきます。さらに、プログラムの実行時に"必要なプロジェクトでのエラー"のダイアログが表示されます。("続行"を押すと実行できます。)
警告 問題がある箇所に黄色の点線が引かれ、該当する行及びファイル名にエクスクラメーションマーク(!)がつきます。実行時にダイアログは出ません。
情報 問題がある箇所に青の波線が引かれ、該当する行及びファイル名に"i"マークがつきます。実行時にダイアログは出ません。
無視 何も表示しません。

エラー

エラーの時の表示です。

f:id:yucatio:20200110081144p:plain

実行時にダイアログが表示されます↓

f:id:yucatio:20200110081158p:plain

警告

警告の時の表示です。

f:id:yucatio:20200110081127p:plain

情報

情報の時の表示です。

f:id:yucatio:20200110081113p:plain

無視

無視の時は何も表示されません。

f:id:yucatio:20200110081101p:plain

エラー、警告、情報の一覧を表示する

現在のワークスペースの警告の一覧を表示するには、ウィンドウ > ビューの表示 > その他 > 一般 > マーカーを開きます。

f:id:yucatio:20200110081050p:plain

"マーカー"のビューに現在のワークスペース内に存在するエラーや警告が表示されます。各項目をクリックすると該当箇所へジャンプすることができます。

f:id:yucatio:20200110081025p:plain

以上、eclipseの警告設定と各重大度レベルごとの挙動でした。

環境

うっかりミスを防ぐeclipseおすすめ設定6つ【後編】

前編に引き続き、うっかりミスを防止(警告)するeclipseの設定をまとめました。

前編の記事

yucatio.hatenablog.com

セミコロン2つを検知

行末のセミコロンを間違って2つ打ってしまうのもありがちなミスです。

設定 > Java > コンパイラー > エラー/警告 > 潜在的なプログラミングの問題 > 空のステートメントの警告レベルを、"情報"にします。

f:id:yucatio:20200107115743p:plain

設定前↓

f:id:yucatio:20200107121016p:plain

設定後↓

f:id:yucatio:20200107121029p:plain

マウスオーバーするとセミコロンの除去がサジェストされます↓

f:id:yucatio:20200107121040p:plain

何も記述されていないブロックを検出

何も記述されていないブロックを検出する方法です。 何も書かれないブロックが必要な場合もあります。そんなときはコメントを書いておくか消しててほしいものです。

設定 > Java > コンパイラー > エラー/警告 > コード・スタイル > 何も記述のない空のブロックの警告レベルを、"警告"にします。

f:id:yucatio:20200107130435p:plain

設定前↓

f:id:yucatio:20200107130540p:plain

設定後↓

f:id:yucatio:20200107130459p:plain

空ブロックにコードかコメントを書くように促されます↓

f:id:yucatio:20200107130553p:plain

@Overrideのつけ忘れを防ぐ

オーバーライドしたメソッドに@Overrideアノテーションが付いていない場合に警告します。

設定 > Java > コンパイラー > エラー/警告 > 注釈 > '@Override' 注釈の欠落の警告レベルを、"警告"にします。

f:id:yucatio:20200107195325p:plain

設定前↓

f:id:yucatio:20200107195355p:plain

設定後↓

f:id:yucatio:20200107195413p:plain

@Overrideをつけるようにとの警告が表示されるようになりました↓

f:id:yucatio:20200107195433p:plain

環境

あとがき

以上、うっかりミスを防ぐためのおすすめeclipse設定でした。書きながら、とりあえず 設定 > Java > コンパイラー > エラー/警告の"無視"となっているところを全て"情報"以上にすればよいのではと思うのでした。

うっかりミスを防ぐeclipseおすすめ設定6つ【前編】

こんにちは。プログラミングでうっかりミスをしてしまうブログ主です。特にスペルミスがひどいです。 レビューで指摘されると申し訳無い気持ちになるので、そのようなうっかりミスを防止(警告)するeclipseの設定をまとめました。

空白の表示

空白タブ、全角空白、改行文字などを表示するオプションです。

設定 > 一般 > エディター > テキスト・エディター > 空白文字を表示にチェックを入れます。

f:id:yucatio:20200107085812p:plain

次に、可視性の構成をクリックして全てチェックを入れます。

f:id:yucatio:20200107085824p:plain

設定前↓

f:id:yucatio:20200107085900p:plain

設定後↓

f:id:yucatio:20200107085911p:plain

タブは^、スペースは.、全角スペースはで表示されました。改行コードは、LF(Unixの改行コード)は、CRLF(Windowsの改行コード)はで表示されます。

チーム開発時にONにしてほしいオプションナンバー1です。空白とタブを混ぜると後々見にくさの原因になります。

スペルチェック

スペルをチェックをするオプションです。

設定 > 一般 > エディター > テキスト・エディター > スペル > スペル・チェックを使用可能にするにチェックを入れます。

f:id:yucatio:20200107091023p:plain

設定前↓

f:id:yucatio:20200107091117p:plain

設定後↓

f:id:yucatio:20200107091131p:plain

赤の波線が出ている箇所にマウスオーバーすると、修正の候補が表示されます↓

f:id:yucatio:20200107091144p:plain

Javadocのチェック

Javadoc@paramなどの項目がメソッドの定義と一致しているかをチェックするオプションです。リファクタリングのときにJavadocを修正し忘れることはよくあるので入れておきたい設定です。

設定 > Java > コンパイラー > Javadocを開き、以下のような設定にします。

f:id:yucatio:20200107113825p:plain

各設定項目の挙動についてはこちらの記事をご覧ください。

yucatio.hatenablog.com

yucatio.hatenablog.com

設定前↓

f:id:yucatio:20200107113839p:plain

設定後↓

f:id:yucatio:20200107113905p:plain

メソッドで宣言されていないパラメータがJavadocにあると警告を出します↓

f:id:yucatio:20200107113920p:plain

returnに何も記述されていないと警告を出します↓

f:id:yucatio:20200107113931p:plain

存在しないクラスやメソッドを参照すると警告を出します↓

f:id:yucatio:20200107113942p:plain

メソッド宣言にあって、Javadocに無いパラメータがあるときに警告を出します↓

f:id:yucatio:20200107113954p:plain

環境

後編に続く

長くなったので続きます。

yucatio.hatenablog.com

Pythonで辞書が格納されたリストを複数のキーで並べ変える

辞書を格納したリストがある時、複数キーで並び変える方法を紹介します。例えば、以下のような辞書が格納された配列で、まずprice順に並び変え、priceが同じだったら、weightの順番に並び変えたい場合の方法です。

list1 = [
    {'name': 'ぶどう',   'price': 5000, 'weight': 1000},
    {'name': 'もも',     'price': 3000, 'weight': 2000},
    {'name': 'りんご',   'price': 5000, 'weight': 5000},
    {'name': 'バナナ',   'price': 1500, 'weight': 1000},
    {'name': 'メロン',   'price': 5000, 'weight': 1200},
    {'name': 'マンゴー', 'price': 10000, 'weight': 900},
    {'name': 'みかん',  'price': 1500, 'weight': 5000},
]

keyにitemgetterを使用する

辞書の値で並び替える場合、itemgetter関数が便利です。

参考: ソート HOW TO — Python 3.8.1 ドキュメント

itemgetterを使用するときは、 パラメータに辞書のキー名を並び替えの優先順位の順に書きます。

sorted(list, key=itemgetter(第1キー, 第2キー, 第3キー))

まずprice順に並び変え、priceが同じだったら、weightの順番に並び変えたい場合はsorted関数のキーにitemgetter('price', 'weight')を指定します。

コードと並べ替えの結果です。

from operator import itemgetter

# list1は上記のlist1と同様
list1 = [...]

# 並べ替え
sorted_list = sorted(list1, key=itemgetter('price', 'weight'))

# 出力
print(f"{'name':<8}{'price':>8}{'weight':>8}")
print('-' * 24)
for item1 in sorted_list:
    print(f"{item1['name']:<8}{item1['price']:>8}{item1['weight']:>8}")

# name       price  weight
# --------------------------------
# バナナ         1500    1000
# みかん         1500    5000
# もも          3000    2000
# ぶどう         5000    1000
# メロン         5000    1200
# りんご         5000    5000
# マンゴー       10000     900

priceで最初に並べ替え、priceが同じ場合はweightで並び替えられています。デフォルトなのでいずれも昇順で並び替えられています。

keyにlambda関数を使用する

より一般的に複数のキーで並び替えたいときは、keyに指定する関数の戻り値にタプルを指定します。

例えば、グラム単価(price/weight)で並び替えた後、同じグラム単価であれば、priceで並び替えるようなプログラムは以下になります。

# list1は上記のlist1と同様
list1 = [...]

# 並べ替え
sorted_list = sorted(list1, key=lambda item: (item['price'] / item['weight'], item['price']))

# 出力
print(f"{'name':<8}{'price(1g)':>10}{'price':>8}{'weight':>8}")
print('-' * 34)
for item1 in sorted_list:
    print(f"{item1['name']:<8}{item1['price'] / item1['weight']:>10.2f}{item1['price']:>8}{item1['weight']:>8}")

# name     price(1g)   price  weight
# ----------------------------------
# みかん           0.30    1500    5000
# りんご           1.00    5000    5000
# バナナ           1.50    1500    1000
# もも            1.50    3000    2000
# メロン           4.17    5000    1200
# ぶどう           5.00    5000    1000
# マンゴー         11.11   10000     900

グラム単価で並び替えた後、同じグラム単価であれば、priceで並び替えることができました。 マンゴーのグラム単価高いですね。

以上でPythonで辞書が格納されたリストを複数のキーで並べ変えることができました。

環境