はじめに
Qiitaで新人プログラマ応援企画があるということで,自分の経験をもとに学生時代のプログラミングと仕事上でのプログラミングの違いを書いてみることにしました。
私自身はの今までの経験は,以下のような感じです。
- 10年近く商用ソフトウェアの開発を経験
- アプリケーションではなくその基盤となるミドルウェアの開発が中心
- 使用してきた言語はC/Javaなどが多い(最近はRuby/Python/JavaScriptなども。。。)
わたしの主観による内容ですので,「いやいや違うよ!」とか「本当かなあ??」と思われるところもあるかと思いますが,「こういう考え方もあるのね!」と思っていただければ幸いです。
学生時代のプログラミング
一例として競技プログラミングのような問題を解くプログラミングを考えてみます。
2つの整数を入力として受け取り,その和を出力するプログラムを考えます(よくatCoderやpaizaとかである問題みたいな感じです)。
10 5
この入力を受けとると,以下のように10+5の結果(つまり15)を出力するプログラムを書くというものです。
簡単のために,2つの入力値の範囲は0~100の整数(十進数)としましょう。
15
とりあえず,さくっと答えを求めるプログラムを作ると,こんな感じでしょうか。
[a,b] = [int(s) for s in input().split(" ")]
print(a+b)
うん,できた!いい感じ!
仕事上でのプログラミング
さくっとできたこのプログラムが非常に評判になり,「かんたん足し算」として商用プログラムとして売ることになりました。いや,こんなの売れないでしょ!というツッコミは大いにあるでしょうが,ここではそういうお話として考えてください。
ただ,このままでは売り物にならないというのが私の思う,仕事上のプログラミングと学生時代のプログラミングとの大きな差かな?と思っています。
なぜ,売り物にならないのか。それは,エラー処理が全くないことです。
例えば,この「かんたん足し算」を買ったお客様は,どんな入力をするかわからないです。例えば,1~100しか入力してはダメと仕様に書いてあっても,もっと大きな数字を入力されるかもしれません。もしくは,間違って3つ数字を書いてしまったり,アルファベットを書いてしまうこともあるかもしれません。
1例として,数字でない文字を入力してしまったケースを考えてみます。
私の手元では,こんな感じになりました。
10 a
Traceback (most recent call last):
File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/home/charoro/.vscode-server/extensions/ms-python.python-2021.3.680753044/pythonFiles/lib/python/debugpy/__main__.py", line 45, in <module>
cli.main()
File "/home/charoro/.vscode-server/extensions/ms-python.python-2021.3.680753044/pythonFiles/lib/python/debugpy/../debugpy/server/cli.py", line 444, in main
run()
File "/home/charoro/.vscode-server/extensions/ms-python.python-2021.3.680753044/pythonFiles/lib/python/debugpy/../debugpy/server/cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "/usr/lib/python3.8/runpy.py", line 265, in run_path
return _run_module_code(code, init_globals, run_name,
File "/usr/lib/python3.8/runpy.py", line 97, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/usr/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/home/charoro/workspace/test/test.py", line 1, in <module>
[a,b] = [int(s) for s in input().split(" ")]
File "/home/charoro/workspace/test/test.py", line 1, in <listcomp>
[a,b] = [int(s) for s in input().split(" ")]
ValueError: invalid literal for int() with base 10: 'a'
例外が発生して,バックトレースが出てしまいました。もし「かんたん足し算」を買ったお客様がこんなバックトレースをみたらどうするでしょう?
例えば,私が電卓を買って,入力を間違ってこんなエラーが出たら,「え!?」っとびっくりしてしまうと思います。
プログラミングを知らないお客様にとってはこんな内部のエラーの内容を言われたってわからないです。
では,どうしたらいいでしょう。その答えがきちんとエラー処理を作るということです。
今回の場合ですと,入力値のチェックが必要になります。チェックしなければならない内容は,こんなものでしょうか(もしかするともっとあるかもしれません)。
- 入力値が半角スペース区切りで2こあること
- 入力値は半角数字[0-9]のみで記載されていること
- 入力値は1~100の値であること
では,このチェックをいれたプログラムを再度作ってみましょう。
import sys
import re
# 入力値データを取得する
try:
input_data_list = input().split(' ')
except EOFError:
print('エラー:入力するデータがありません')
exit(1)
# データの数をチェックする
if len(input_data_list) != 2:
print('エラー:入力するデータは半角空白で区切って2個書いてください',file=sys.stderr,flush=True)
exit(1)
# 入力値が数字であることをチェックする
if re.match('^\d+$',input_data_list[0], re.A) == None:
print('エラー:1つ目の入力値が整数ではありません。入力値は半角数字で書いてください',file=sys.stderr,flush=True)
exit(1)
if re.match('^\d+$',input_data_list[1], re.A) == None:
print('エラー:2つ目の入力値が整数ではありません。入力値は半角数字で書いてください',file=sys.stderr,flush=True)
exit(1)
# 入力値を数字に変換
a = int(input_data_list[0])
b = int(input_data_list[1])
if a < 1 or a > 100:
print('エラー:1つ目の入力値が1~100の範囲ではありません',file=sys.stderr,flush=True)
exit(1)
if b < 1 or b > 100:
print('エラー:2つ目の入力値が1~100の範囲ではありません',file=sys.stderr,flush=True)
exit(1)
print(a+b)
先ほどわずか2行だったプログラムが,改行のみの行やコメントを除いても20行以上になっています。
わたしが先輩から教わったのは,
- 商用のプログラムでは全体のソースコードのうち,エラー処理が7割以上になる。
- メイン処理をきちんと作るのは当たり前。エラー処理をきちんと作れて初めて売り物になる。
ということでした。こういったきちんとしたエラー処理が,学生時代のプログラミングとの1つの大きな違いなのかなと思います。
おわりに
あたらしくお仕事でプログラミングをすることになった人たちに,エラー処理という観点を通して,少しでも学生時代のプログラミングとお仕事でのプログラミングの違いを実感していただけたら幸いです。