既に定義されたAPIインターフェースに対して、なぜ開発が遅いのでしょうか?他の作業が挟まることもありますが、それでもなお遅いと感じるのは、思考の問題なのか、それともテクニックの問題なのでしょうか。
- 細心さを持ち、バグを減らそう!
同僚から圧縮ファイルのアップロード機能の実装を依頼され、以前作成した圧縮関数があったので、そのままコピー&ペーストしました。私は、コードレビューのついでに圧縮の仕組みを理解しようとソースコードを確認したところ、バグを発見しました。
int temp;
while(temp = inputStream.read()){
outputStream.write(temp);
}
このファイルの読み書きコードは、何度も目にして非常に馴染みのあるものです。そのため、私はすぐにバグに気づきました。このコードはファイルに何を書き込んでいるのでしょうか。幸いにも自分で開発中に問題に気づけたため、テストフェーズで問題が発覚するよりは良い結果でした。以前、インターフェースの仕様を確認する際にも大文字小文字を混同し、間違ったドキュメントエンコーディングを相手に渡したことがあります。また、迷いの自信から、サービスをデプロイした後、ステータスを確認せずにその場を去り、時間を節約したつもりでしたが、実際には問題の原因を特定するために多くの時間を無駄にしていました。
プログラマーとして、厳密な思考と習慣を持つことが重要です。自分が書いたコードが何度も実行されることを理解し、常にその安定性と信頼性を保つ必要があります。このような小さなことから一つずつ丁寧に取り組むことで、仕事で如鱼得水となり、昇進や給与アップにも繋がります。
public class LegacyTool {
@Autowired
private DataRepository dataRepo;
}
このSpring Bootプロジェクト内の見た目は普通のコードですが、バグを含んでいました。これはテスト担当者がテストに失敗し、ログを確認したところNullPointerExceptionが発生したことで発覚しました。Springの依存性注入の仕組みを深く理解していなければ、このエラーは発見するのが非常に困難です。気づきましたか?(LegacyToolクラスはSpringに管理されていないため、DataRepositoryは自動的に注入されません)。したがって、原理を深く理解し、それを基にして自分の知識体系を構築することが大切です。
- アーキテクトを困らせないように!
一日の作業は非常に詰まっているにも関わらず、なぜか効率が上がりません。コードのコメントアウトやJVMパラメータの追加などの過程で、不注意なミスをしてしまいました。例えば、コメントアウトを元に戻す際に選択範囲を間違え、JVMパラメータを追加する際に余分な内容をコピーしてしまいました。この作業は本来簡単で、間違えるはずのないものですが、考えずに行動すると、間違える可能性があります。少なくとも二箇所でこのミスを発見し、修正できるはずです。一つはコピー時、もう一つはペースト時です。
その後、午後になり、リリースまで時間が迫ってきました。しかし、テスト担当者からまだ問題があると言われました。ログを確認しましたが、ログが少なく、問題の原因を特定できません。コードを自分で確認しても、どこに問題があるのか分かりません。仕方なくログを追加し、テスト担当者に再実行を依頼しました。すると、渡されたパラメータが後から見えました。パラメータをコピーし、ローカルで呼び出そうとしましたが、デプロイする前に少し修正したかったのです。なぜなら、ローカルで環境を構築するのは面倒だからです。しかし、同僚が「またデプロイするんだ」と冗談を言ったことで、私は非常に気分が悪くなりました。できるだけ一度で成功させ、ローカルで調整して問題を解決し、頻繁に問題を起こさないようにしたいのです。環境が複雑であっても構築する必要があります。幸いにも、この機能はデータベース操作を含んでおらず、リスクの高い領域ではありません。その後、ローカルでデバッグを始めると、多くの問題が見つかりました。例えば、圧縮の問題、ファイルの展開、ファイルパスの問題などです。自分で真剣に調べなければ、本当に長い時間をかけて解決する必要がありました。
急いでいる中では、思考も散漫になり、繰り返しデバッグして問題を発見し、解決するしかありませんでした。書いたコードも肥大化してしまいました。これについて、私はただ「業務を正しく実装できればそれで十分」と言いたいだけです。もちろん、業務をよりエレガントに書きたいと思っていますが、実際には非常に難しく、時間がかかります。
自分でコードを書くとき、多くの基本的な操作ができないのは、基礎がまだしっかりしていないからです。常に手でコードを書き、最後に圧縮ファイルの基本概念を確認する必要があります。
// ZipEntryオブジェクト
ZipEntry zipEntry;
// ZipOutputStreamのインスタンス
ZipOutputStream zipStream;
// 圧縮ファイル内のファイル名を取得
String fileName = zipEntry.getName();
// ディレクトリ内のすべてのファイルを取得
File[] files = sourceDir.listFiles();
// 通常のファイルストリームと圧縮ファイルストリームの違い:
// 通常のファイルストリームはそのまま使用できますが、圧縮されたファイルストリームは展開後でなければ使用できません。これは、動画データが転送される際に圧縮されるのと同じです。
// ResponseEntity<Resource> res = restTemplate.getEntity(); // ファイル転送のインターフェースをローカルで練習してみましょう。これは双方向で事前に合意されたデータ転送仕様です。