ホームページ  >  記事  >  Java  >  Java プロジェクト エンジニアリングのサンプル コード分析

Java プロジェクト エンジニアリングのサンプル コード分析

PHPz
PHPz転載
2023-04-21 16:04:081028ブラウズ

    良いコードを測定するための原則

    1 コード指標の評価

    実際、私たちが普段口で言うことは「良い」ものです。 「腐った」はコードの品質を表します。 「良い」は一般に高品質のコードを意味し、「悪い」は一般に低品質のコードを意味します。コードの品質の説明については、「良い」「悪い」といった比較的単純かつ大雑把な説明のほかに、その他にもさまざまな説明をよく耳にします。これらの記述方法は、意味的により豊富で、より専門的で、より詳細です。一般に、可読性、保守性、拡張性、再利用性、柔軟性、テスト容易性などの基準がいくつかあります。

    ## ソフトウェア設計の第一人者、マーティン・ファウラーはかつてこう言いました。「どんな愚か者でも、コンピュータが理解できるコードを書くことができます。優れたプログラマは、人間が理解できるコードを書くことができます。中国語に訳すと、「どんな愚か者でも、コンピュータが理解できるコードを書くことができます。良いです」プログラマーは人間が理解できるコードを書くことができます。」 Google 内には Readability と呼ばれる認定資格さえあります。この認定を取得したエンジニアのみが、コードレビュー中に他の人がコードを提出することを承認する資格を持ちます。コードの読みやすさがいかに重要であるかがわかりますが、結局のところ、コードが書かれて実行される回数よりも読み取られる回数のほうがはるかに多いのです。

    Java プロジェクト エンジニアリングのサンプル コード分析  私は個人的に、コードの可読性はコードの品質を評価するための最も重要な指標の 1 つであるべきだと信じています。コードを書くときは、コードが読みやすく理解しやすいかどうかを常に考慮する必要があります。さらに、コードの読みやすさはコードの保守性に大きく影響します。結局のところ、バグを修正する場合でも、機能コードを変更して追加する場合でも、最初に行う必要があるのはコードを理解することです。コードをよく理解していないと、検討不足により新たなバグが発生する可能性が高くなります。

      読みやすさは非常に重要なので、コードの読みやすさをどのように評価すればよいでしょうか?コードがコーディング規約に準拠しているか、意味のあるネーミングか、コメントが詳細か、関数の長さは適切か、モジュール分けは明確か、高凝集性・低結合性を満たしているかなどを確認する必要があります。また、良い面から見ると、すべての評価指標を網羅することは難しいということも感じていただけると思います。これが、可読性を数値化できない理由でもあります。

      実際、コードレビューはコードの読みやすさをテストする良い方法です。あなたが作成したコードを同僚が簡単に読むことができる場合、それはコードの可読性が非常に優れていることを意味します。同僚がコードを読んだときに多くの質問をする場合、それはコードの可読性を改善する必要があることを意味します。

    ##保守性保守性

    ##  一般に、元のコード設計を破壊することなくバグを迅速に修正したり、新しい機能を追加したりできる機能を指します。新しいバグは発生せず、コードが比較的保守しやすいことを示しています。コーディング開発に関して言えば、いわゆる「メンテナンス」とは、バグを修正したり、古いコードを修正したり、新しいコードを追加したりすることに他なりません。いわゆる「コードの保守が容易である」とは、元のコード設計を破壊したり、新しいバグを導入したりすることなく、コードを迅速に変更または追加できることを意味します。いわゆる「コードの保守が容易ではない」とは、コードの変更や追加には新たなバグが発生する大きなリスクがあり、完了までに長い時間がかかることを意味します。

    • 拡張性 extensibility

      将来の新しい要件に直面してコードを変更できる能力。一般的に言えば、新しい要件を開発する機能 場合によっては、オンデマンドで開発する機能は、元のコードを変更せずに、またはごくわずかな変更で実現でき、一部の機能拡張ポイントは通常予約されています。

    • 再利用性

    ##   車輪の再発明を避けるようにしてください。つまり、いくつかの共通のコード ロジックを作成し、コードからの分離を維持できます。上位層のビジネス コード

    • 柔軟性 柔軟性

      この用語は比較的広い意味を持ちます。通常、保守性、スケーラビリティ、再利用性と同様です。

    • テスト性

      主に、単一のテスト中の記述に反映されます。これは 2 つの側面に反映されています:

    1. 単体テストは簡単に作成できますか?
    • 2. 単体テストを作成するとき、環境や他のサービスをリモートで呼び出す言い訳に頼ることはできません。可能な限りデータを模擬し、サービスを分離したままにします。チームの全員がこの仕様に従うのは困難ですが、私たちのチームには、各機能のコードが 50 行を超えてはならず、コードはできるだけ短くするという必須要件があります。

      これらの寸法は、コードの寸法を判断するためのより重要な指標の一部です。
    2 指導理論

      高凝集性と低結合性は、ほぼすべてのプログラマーが口にする言葉ですが、この用語はあまりにも広範で正確すぎるため、賢いプログラマーはいくつかのオブジェクトを提案しています。コードの品質を測定するための 指向の設計原則:

    • オープンクローズ原則OCP (オープンクローズ原則)

    • 単一責任原則SRP (単一責任原則)

    • 依存性逆転の原理 DIP (依存性逆転の原理)

    • 最小知識原理 LKP (最小知識の原理)) / デメテルの法則

    • リスコフ置換原則 LSP (リスコフ置換原則)

    • インターフェース分離原則ISP (インターフェース分離原則)

    • 組み合わせ/集合体再利用原則 CARP (複合/集約再利用の原則)

    ##  これらの理論は誰もがよく知っているはずです。これらはコードを書くためのガイドラインです。これらの原則に従って、開発されたコードは、高い凝集性と、言い換えれば、これらの原則を使用してコードの品質を測定できます。

    コード実装スキル

    すべてのエンジニアは高品質のコードを書きたいと思っており、成長せずに苦情を言われるような悪いコードを書き続けることは望まないと思います。では、どうすれば高品質のコードを書くことができるのでしょうか?高品質なコードとは何かということで、最も一般的に使用される重要な 7 つの評価指標について説明しました。したがって、高品質のコードを書く方法を尋ねることは、保守しやすく、読みやすく、拡張しやすく、柔軟性があり、簡潔で、再利用可能で、テスト可能なコードをどのように書くかを尋ねることと同じです。

    1 抽象化能力

      抽象的思考はエンジニアにとって最も重要な思考能力です。ソフトウェア テクノロジー それは本質的に抽象芸術です。当社のエンジニアは、日々抽象的思考を使用して、問題領域を分析、要約、合成、判断、推論することで、さまざまな概念を抽象化し、概念間の関係を探索し、プログラミング言語を通じてビジネス機能を実現する必要があります。時間はコードを書くことではなく、要件を整理し、概念を明確にし、要件を全体的に理解することにあります。抽象化する能力により、私と私のチームは、それがコーディングとデザインにもたらす質的な変化を感じます。

    ケース 1: 非同期 Excel エクスポート

    実際、Excel エクスポート機能はプロジェクトのあらゆる場所で見ることができ、特に当社の運用では、一度にできるだけ多くのデータをエクスポートすることを望んでいます。システムに問題を引き起こさないようにするためのプレッシャーが多すぎる 大量のデータのエクスポートは通常非同期で実行されますが、このような単純な機能をどのように抽象化すればよいでしょうか?

    一般的な記述方法:

    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 サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。