Home  >  Article  >  Java  >  Java project engineering example code analysis

Java project engineering example code analysis

PHPz
PHPzforward
2023-04-21 16:04:081009browse

    Principles for measuring good code

    1 Evaluating code indicators

    In fact, what we usually say in our mouths are "good" and "Rotten" is a description of code quality. "Good" generally means high-quality code, and "bad" generally means low-quality code. Regarding the description of code quality, in addition to relatively simple and crude descriptions such as "good" and "bad", we often hear many other descriptions. These description methods are semantically richer, more professional, and more detailed. I collected and sorted it out and listed it below. Generally, there are several standards, namely readability, maintainability, scalability, reusability, flexibility, testability, etc.

    Java project engineering example code analysis

    Readabilityreadability

    Software design guru Martin Fowler once said: “Any fool can write code that a computer can understand. Good programmers write code that humans can understand. Translated into Chinese: "Any fool can write code that computers can understand. Good programmers can write code that humans can understand." There is even a certification within Google called Readability. Only engineers who have obtained this certification are qualified to approve others to submit code during code review. It can be seen how important the readability of the code is. After all, the number of times the code is read far exceeds the number of times it is written and executed.

      I personally believe that code readability should be one of the most important indicators for evaluating code quality. When we write code, we must always consider whether the code is easy to read and understand. In addition, the readability of the code affects the maintainability of the code to a great extent. After all, whether we are fixing bugs or modifying and adding functional code, the first thing we have to do is to understand the code. If you don't understand the code well, it's very likely that new bugs will be introduced due to insufficient consideration.

      Since readability is so important, how should we evaluate the readability of a piece of code? We need to check whether the code complies with coding standards, whether the naming is meaningful, whether the comments are detailed, whether the function length is appropriate, whether the module division is clear, whether it meets high cohesion and low coupling, etc. You should also be able to feel that from the positive side, it is difficult for us to give a list that covers all evaluation indicators. This is also why we cannot quantify readability.

      In fact, code review is a good way to test the readability of the code. If your colleagues can easily read the code you wrote, it means that the readability of your code is very good; if your colleagues have a lot of questions when reading your code, it means that the readability of your code needs to be improved.

    • Maintainabilitymaintainability

    ##  Generally refers to the ability to quickly modify bugs or add new features without destroying the original code design. The code will not bring new bugs, indicating that the code is relatively maintainable. When it comes to coding development, the so-called "maintenance" is nothing more than fixing bugs, modifying old code, and adding new code. The so-called "code is easy to maintain" means that the code can be quickly modified or added without destroying the original code design or introducing new bugs. The so-called "code is not easy to maintain" means that modifying or adding code requires a great risk of introducing new bugs and takes a long time to complete.

    • Extensibility extensibility

      The ability of the code to change in the face of new requirements in the future. Generally speaking, the ability to develop new requirements Sometimes, the ability to develop on demand can be achieved without modifying the original code or with very few modifications, and some functional expansion points are usually reserved.

    • Reusability

    • ##   Try to avoid reinventing the wheel, that is, you can precipitate some common code logic and maintain Decoupling from the upper-layer business code

      Flexibility flexibility
    •   This term is relatively broad. Usually similar to maintainability, scalability and reusability

      Testability
    •   Mainly reflected in writing During a single test. This is reflected in two aspects:

    1. Is unit testing easy to write?

    2. When writing unit tests, you cannot rely on the environment or the excuse to call other services remotely, and mock data as much as possible , keeping the services decoupled. Although it is difficult for everyone in the team to follow this specification, our team has a mandatory requirement that each functional function cannot exceed 50 lines of code, and the code is required to be as short as possible.

    These dimensions are some of the more important indicators for judging code dimensions.

    2 Guiding Theory

      High cohesion and low coupling are words that almost every programmer talks about, but this term is too broad and too correct, so Smart programmers have proposed several object-oriented design principles to measure the quality of code:

    • Open-Close Principle OCP (The Open-Close Principle)

    • Single Responsibility PrincipleSRP (Single Responsibility Principle)

    • Dependency Inversion Principle DIP (Dependence Inversion Principle)

    • Least Knowledge Principle LKP (Least Knowledge Principle)) / Law Of Demeter

    • Liskov Substitution Principle LSP (Liskov Substitution Principle)

    • Interface Segregation PrincipleISP (Interface Segregation Principle)

    • combination /Aggregate Reuse Principle CARP (Composite/Aggregate Reuse Principle)

    ##  Everyone must be familiar with these theories. They are guidelines for us to write code. According to these principles The developed code has the characteristics of high cohesion and low coupling. In other words, we can use these principles to measure the quality of the code.

    Code Implementation Skills

    I believe that every engineer wants to write high-quality code, and does not want to keep writing bad code that has not grown and been complained about. So how can we write high-quality code? Regarding what high-quality code is, we have just talked about the seven most commonly used and important evaluation indicators. Therefore, asking how to write high-quality code is equivalent to asking how to write code that is easy to maintain, easy to read, easy to expand, flexible, concise, reusable, and testable. But writing good code also requires It does not happen overnight, it requires a lot of practice and accumulation. Here is a brief example:

    1 Abstract ability

      Abstract thinking is the most important thinking ability for our engineers, because software technology It is essentially an abstract art. Our engineers have to use abstract thinking every day to analyze, summarize, synthesize, judge, and reason about the problem domain, thereby abstracting various concepts, exploring the relationship between concepts, and then realizing business functions through programming languages. Therefore, we Most of the time is not writing code, but sorting out requirements, clarifying concepts, and gaining an overall understanding of requirements. The ability to abstract makes me and my team feel the qualitative changes it brings to us in coding and design.

    Case 1: Asynchronous Excel Export

    In fact, the Excel export function can be seen everywhere in our project, especially our operations hope to export as much data as possible at one time, in order not to bring problems to our system There is too much pressure. The export of large amounts of data is generally performed asynchronously. For such a simple function, how should it be abstracted?

    Common writing method:

    public String exportXXX(参数) throws Exception {
    	//业务实现
    }
    public String exportXXX2(参数) throws Exception {
    	//业务实现
    }

    Abstract writing method:

    We can actually regard each asynchronous export as an asynchronous task, and the content that each task can export are different, so the export can be abstracted as a method, and each specific implementation class can implement the export of different contents, as follows:

    // 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;
        }
    }

    Case 2: System notification

    In Today, when microservices are popular, in order to improve system throughput, system responsibilities are becoming more and more detailed. Each system module needs to frequently exchange data. So for complex data interaction scenarios, such as our allocation order, the allocation order needs to be reversed with Many systems interact with each other, including stores, warehouses, and inventory modules. How should we abstract it? The following are code examples for allocating interactions with each system

    //接口定义
    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 {
            //业务代码实现
        }
    }

    In fact, we are interacting with other systems At that time, we can abstract each interactive action into a notification event. Every time there is an interaction, just write an event notification event.

    2 Principle of combination/aggregation reuse

      As for the principle of combination/aggregation reuse, in fact we often encounter it during the project process. For example, we often manage various documents in the project. , such as purchase orders, transfer orders, receipt orders, etc., and there are various verifications for each document. Let's first look at a code to create a transfer order. How to download it specifically:

    //接口定义
    public interface TransferValidator {
        boolean validator(CreateTransferCtx ctx) throws OspException;
    }
    //接口实现1
    public class W2sCrossPoQtyValidator implements TransferValidator {
        @Override
        public boolean validator(CreateTransferCtx ctx) throws OspException {
            //较验器代码实现
        }
    //接口实现2
    public class W2sStoreBarcodeSaleLimitValidator implements TransferValidator {
        @Override
        public boolean validator(CreateTransferCtx ctx) throws OspException {
            //较验器代码实现
        }
    }
    //较验器组装
    public class TransferValidators {
        public ValidatorChain newChain() {
            return new ValidatorChain();
        }
        public class ValidatorChain {
            private final List<TransferValidator> validators = new ArrayList<>();
            public ValidatorChain qtyValidator() {
                validators.add(qtyValidator);
                return this;
            }
            public ValidatorChain transferRouteCfgValidator() {
                validators.add(transferRouteCfgValidator);
                return this;
            }
            public ValidatorChain prodValidator() {
                validators.add(prodValidator);
                return this;
            }
            public ValidatorChain w2sWarehouseStoreValidator() {
                validators.add(w2sWarehouseStoreValidator);
                return this;
            }
            public ValidatorChain w2sStoreBarcodeSaleLimitValidator() {
                validators.add(w2sStoreBarcodeSaleLimitValidator);
                return this;
            }
            public ValidatorChain w2sAssignPoValidator() {
                validators.add(w2sAssignPoValidator);
                return this;
            }
            public ValidatorChain w2sCrossPoValidator() {
                validators.add(w2sCrossPoValidator);
                return this;
            }
            public ValidatorChain w2sCrossPoQtyValidator() {
                validators.add(w2sCrossPoQtyValidator);
                return this;
            }
            public ValidatorChain w2sCross4XupValidator() {
                validators.add(w2sCross4XupValidator);
                return this;
            }
            public ValidatorChain repeatLineValidator() {
                validators.add(repeatLineValidator);
                return this;
            }
            public ValidatorChain sstradeBarcodeValidator() {
                validators.add(sstradeBarcodeValidator);
                return this;
            }
            public ValidatorChain s2wWarehouseStoreValidator() {
                validators.add(s2wWarehouseStoreValidator);
                return this;
            }
            public boolean validator(CreateTransferCtx ctx) throws OspException {
                for (TransferValidator validator : validators) {
                    if (!validator.validator(ctx)) {
                        return false;
                    }
                }
                return true;
            }
        }
    }
    //业务代码使用
    public interface TransferCreator {
        boolean createOrder(CreateTransferCtx ctx) throws OspException;
    }
    public abstract class DefaultTransferCreator implements TransferCreator {
         @Override
        public boolean createOrder(CreateTransferCtx ctx) throws OspException {
            validator(ctx)
            //实现业务逻辑
        }
        protected abstract boolean validator(CreateTransferCtx ctx) throws OspException;
     }
    //店仓调拨单 
    public class S2wRefundCreator extends DefaultTransferCreator {
    	//较验器自由组装
        @Override
        protected boolean validator(CreateTransferCtx ctx) throws OspException {
            return transferValidators.newChain()
                    .qtyValidator()
                    .transferRouteCfgValidator()
                    .prodValidator()
                    .validator(ctx);
        }
    }

    The above is the detailed content of Java project engineering example code analysis. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete