実際、私たちが普段口で言うことは「良い」ものです。 「腐った」はコードの品質を表します。 「良い」は一般に高品質のコードを意味し、「悪い」は一般に低品質のコードを意味します。コードの品質の説明については、「良い」「悪い」といった比較的単純かつ大雑把な説明のほかに、その他にもさまざまな説明をよく耳にします。これらの記述方法は、意味的により豊富で、より専門的で、より詳細です。一般に、可読性、保守性、拡張性、再利用性、柔軟性、テスト容易性などの基準がいくつかあります。
## ソフトウェア設計の第一人者、マーティン・ファウラーはかつてこう言いました。「どんな愚か者でも、コンピュータが理解できるコードを書くことができます。優れたプログラマは、人間が理解できるコードを書くことができます。中国語に訳すと、「どんな愚か者でも、コンピュータが理解できるコードを書くことができます。良いです」プログラマーは人間が理解できるコードを書くことができます。」 Google 内には Readability と呼ばれる認定資格さえあります。この認定を取得したエンジニアのみが、コードレビュー中に他の人がコードを提出することを承認する資格を持ちます。コードの読みやすさがいかに重要であるかがわかりますが、結局のところ、コードが書かれて実行される回数よりも読み取られる回数のほうがはるかに多いのです。私は個人的に、コードの可読性はコードの品質を評価するための最も重要な指標の 1 つであるべきだと信じています。コードを書くときは、コードが読みやすく理解しやすいかどうかを常に考慮する必要があります。さらに、コードの読みやすさはコードの保守性に大きく影響します。結局のところ、バグを修正する場合でも、機能コードを変更して追加する場合でも、最初に行う必要があるのはコードを理解することです。コードをよく理解していないと、検討不足により新たなバグが発生する可能性が高くなります。
読みやすさは非常に重要なので、コードの読みやすさをどのように評価すればよいでしょうか?コードがコーディング規約に準拠しているか、意味のあるネーミングか、コメントが詳細か、関数の長さは適切か、モジュール分けは明確か、高凝集性・低結合性を満たしているかなどを確認する必要があります。また、良い面から見ると、すべての評価指標を網羅することは難しいということも感じていただけると思います。これが、可読性を数値化できない理由でもあります。
実際、コードレビューはコードの読みやすさをテストする良い方法です。あなたが作成したコードを同僚が簡単に読むことができる場合、それはコードの可読性が非常に優れていることを意味します。同僚がコードを読んだときに多くの質問をする場合、それはコードの可読性を改善する必要があることを意味します。
##保守性保守性## 一般に、元のコード設計を破壊することなくバグを迅速に修正したり、新しい機能を追加したりできる機能を指します。新しいバグは発生せず、コードが比較的保守しやすいことを示しています。コーディング開発に関して言えば、いわゆる「メンテナンス」とは、バグを修正したり、古いコードを修正したり、新しいコードを追加したりすることに他なりません。いわゆる「コードの保守が容易である」とは、元のコード設計を破壊したり、新しいバグを導入したりすることなく、コードを迅速に変更または追加できることを意味します。いわゆる「コードの保守が容易ではない」とは、コードの変更や追加には新たなバグが発生する大きなリスクがあり、完了までに長い時間がかかることを意味します。
拡張性 extensibility
将来の新しい要件に直面してコードを変更できる能力。一般的に言えば、新しい要件を開発する機能 場合によっては、オンデマンドで開発する機能は、元のコードを変更せずに、またはごくわずかな変更で実現でき、一部の機能拡張ポイントは通常予約されています。
再利用性
オープンクローズ原則OCP (オープンクローズ原則)
単一責任原則SRP (単一責任原則)
依存性逆転の原理 DIP (依存性逆転の原理)
最小知識原理 LKP (最小知識の原理)) / デメテルの法則
リスコフ置換原則 LSP (リスコフ置換原則)
インターフェース分離原則ISP (インターフェース分離原則)
組み合わせ/集合体再利用原則 CARP (複合/集約再利用の原則)
public String exportXXX(参数) throws Exception { //业务实现 } public String exportXXX2(参数) throws Exception { //业务实现 }抽象的な記述方法: 実際には各非同期エクスポートを非同期タスクとみなすことができ、各タスクがエクスポートできる内容は異なります。したがって、エクスポートはメソッドとして抽象化でき、次のように、特定の実装クラスごとにさまざまなコンテンツのエクスポートを実装できます。
// export excel public interface IExcelExportTask { String export(BizCommonExportTask exportTask) throws Exception; } //样例实现类 XXXXExportTask implements IExcelExportTask { String export(BizCommonExportTask exportTask) throws Exception{ public String export(BizCommonExportTask exportTask) throws Exception { //组织数据筛选条件 TestReq queryReq = GsonUtils.toObject(exportTask.getInputParams(),TestReq.class); String fileName = String.format("%s%s%s", exportTask.getUploadFileName(),System.currentTimeMillis(),".xlsx"); String downUrl = excelService.uploadExcel(fileName, null, new Fetcher<PreOccupyModel>(PreOccupyModel.class) { //循环获取数据 @Override public List<TestModel> fetch(int pageNo, int pageSize) throws OspException{ TestQueryResp resp = testFethchLogic.fetchRecord(queryReq); return pageNo > resp.getPageNum() ? Collections.emptyList() :toExcelModel(resp); } }); return downUrl; } } public class XXXXExportTask1 implements IExcelExportTask { @Override public String export(BizCommonExportTask exportTask) throws OspException { TestQuery query = GsonUtils.toObject(exportTask.getInputParams(), TestQuery .class); String fileName = String.format("%s%s%s", exportTask.getUploadFileName(), System.currentTimeMillis(), ".xlsx"); return excelService.uploadExcel(fileName, null, new Fetcher<ExportItemModel>(TestModel.class) { @Override public List<TestModel> fetch(int pageNo, int pageSize) throws OspException { return XXXXLogic.queryExportItem(query, pageNo, pageSize); } }); } } //导出任务分发器 public class ExcelTaskDispacther extends ApplicationObjectSupport { public boolean dispacthTask(Long taskId) throws OspException { updateTaskStatus(exportTask,CommonExportStatus.CREATING,TransferExportStatus.CREATING,StringUtils.EMPTY); try { String beanName = getBeanName(); ExportTaskHandler exportTaskHandler = getApplicationContext().getBean(beanName , IExcelExportTask .class); if(exportTaskHandler == null) { log.warn(String.format("任务ID[%s]写入配置错误!", taskId)); return false; } updateTaskStatus(exportTask,CommonExportStatus.CREATE_SUCCESS,TransferExportStatus.CREATE_SUCCESS,StringUtils.EMPTY); log.info(String.format("任务ID[%s]RFID为[%s]处理成功", exportTask.getId(),rfid)); return true; } catch(BusiException ex) { log.info("任务ID[{}]失败,原因:{}", exportTask.getId(),ex.getMessage(),ex); updateTaskResult(); } catch(Exception ex) { log.info("任务ID[{}]失败,原因:{}", exportTask.getId(),ex.getMessage(),ex); updateTaskResult(); } return false; } }ケース 2: システム通知マイクロサービスが使用される今日では、一般的なシステムのスループットを向上させるために、システムの責任はますます詳細になってきています。各システム モジュールは頻繁にデータを交換する必要があります。そのため、割り当て順序などの複雑なデータ対話シナリオでは、多くのシステムで割り当て順序を逆にする必要があります。店舗、倉庫、在庫モジュールなど、相互に対話します。これをどのように抽象化すればよいでしょうか? 以下は、各システムとの対話を割り当てるためのコード例です
//接口定义 public interface BizNotificationHandler { /** * 抛异常会当失败处理 * 是否需要重试由BizNotificationStatus返回状态来决定 * @param bizNotification * @return * @throws OspException */ BizNotificationStatus handleNotification(BizNotification bizNotification) throws OspException; } //推送调拨差异数据给库存系统 public class SyncDiffToSimsAndBackQuotaHandler implements BizNotificationHandler { @Override public BizNotificationStatus handleNotification(BizNotification bizNotification) throws OspException { //业务逻辑实现 return BizNotificationStatus.PROCESS_SUCCESS; } } //占用库存 public class TransferOccupyInventoryHandler implements BizNotificationHandler { @Override public BizNotificationStatus handleNotification(BizNotification bizNotification) throws OspException { //业务实现 } } //在GPDC生成新条码 public class GpdcGenerateNewBarcodeHandler implements BizNotificationHandler { @Override public BizNotificationStatus handleNotification(BizNotification bizNotification) throws OspException { //业务代码实现 } }実際には、その時点で他のシステムと対話しています, 各インタラクティブなアクションを通知イベントに抽象化できます。インタラクションがあるたびに、イベント通知イベントを記述するだけです。 2 結合/集約の再利用の原則 結合/集約の再利用の原則については、実際にプロジェクトのプロセスでよく遭遇します。プロジェクトには、発注書、転送オーダー、受領書などのさまざまなドキュメントがあり、ドキュメントごとにさまざまな検証があります。まず転送オーダーを作成するコードを見てみましょう。具体的にダウンロードする方法:
rreee
以上がJava プロジェクト エンジニアリングのサンプル コード分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。