Code Concise 1 - What is Concise Code and Meaningful Naming

        Recently, I joined a start-up company with a small team. After working for a period of time, I found that the code situation in the team was very bad. The team has a total of two product lines and five developers. Each has a code style. It is understandable that each person has their own code style. Requirements changes can be catastrophic. So I plan to re-read a book "The Way of Clean Code" that I read a few years ago - the English name is "clean code", also in order not to let myself go astray.

1. First think about a few questions:

  1. What do we read code? ?
  2. What is the purpose of the code we write? ?
  3. What is good code and what is bad code? ?

Here are my thoughts on these three questions:

  1.  When we read someone else's code, the first thing we need to know is what this code or function does, and secondly, in order to complete the function of the function, which steps are it divided into, and finally the specific steps of these steps detail. For example, the following code: 
        public ProjectMsg addProject(ProjectMsg projectMsg) {
            checkInsertParam(projectMsg);
    
            UserLoginBO userLoginBO = GlobalHolder.getUser();
            AccountUserExtBean accountUserExtBean = (AccountUserExtBean) GlobalHolder.getUserInfoExtParams(); 
    
            projectMsg = buildProjectMsg(projectMsg, userLoginBO, accountUserExtBean);
            ProjectMember projectMember = buildProjectMember(projectMsg, userLoginBO, accountUserExtBean);
            projectMsgMapper.insert(projectMsg);
            projectMemberMapper.insert(projectMember);
    
            return projectMsg;
        }

    From the function name, we can know that the method is to add project data, and its implementation is divided into three steps: check the legality of parameters; build project information, Hou Jian projectMember information; and finally add data. If we put all the implementations of the method together, this is the following code: 

        public ProjectMsg addProject(ProjectMsg projectMsg) {
            AssertsUtil.isFalse(ProjectFlag.validateValue(projectMsg.getFlag()), ResultStatusEnum.PROJECT_FLAG_NOT_VALIDATE);
            if (projectMsg.getFlag().intValue() == ProjectFlag.PERSONAL_MEMBER.getValue().intValue()) {
                AssertsUtil.isNull(projectMsg.getSpaceId(), ResultStatusEnum.PERSONAL_SPACE_CANNOT_BO_NULL);
            } else {
                AssertsUtil.isNull(projectMsg.getWorkspaceId(), ResultStatusEnum.PROJECT_SPACE_CANNOT_BO_NULL);
            }
            AssertsUtil.isBlank(projectMsg.getName(), ResultStatusEnum.PROJECT_NAME_CANNOT_BO_NULL);
            AssertsUtil.isFalse(ProjectStatus.validate(projectMsg.getStatus()), ResultStatusEnum.PROJECT_STATUS_NOT_VALIDATE);
    
            UserLoginBO userLoginBO = GlobalHolder.getUser();
            AccountUserExtBean accountUserExtBean = (AccountUserExtBean) GlobalHolder.getUserInfoExtParams(); 
    
            projectMsg.setCreatorId(userLoginBO.getUid());
            projectMsg.setFlag(accountUserExtBean.getUserType());
            projectMsg.setTanentId(accountUserExtBean.getUserTenantId());
            projectMsg.setOwnerId(userLoginBO.getUid());
            projectMsg.setOwner(userLoginBO.getNickName());
            projectMsg.setOwnerTanentMemberId(accountUserExtBean.getUserTenantMemberId());
            projectMsg.setSpaceId(projectMsg.getWorkspaceId() == null ? projectMsg.getSpaceId() : projectMsg.getWorkspaceId());
            projectMsg.setDelStatus(AssetsDelStatusEnum.NORMAL.getStatus());
        projectMsg.setProjectId(MogicId.nextId(MogicIdEnum.PROJECT_INFO.getBizType()));
    
            ProjectMemberRoleRelation projectMemberRoleRelation = new ProjectMemberRoleRelation();
            projectMemberRoleRelation.setId(MogicId.nextId(MogicIdEnum.PROJECT_MEMBER_INFO.getBizType()));
            projectMemberRoleRelation.setProjectId(projectMsg.getProjectId());
            projectMemberRoleRelation.setTenantId(accountUserExtBean.getUserTenantId());
            projectMemberRoleRelation.setWorkspaceId(projectMsg.getSpaceId());
            projectMemberRoleRelation.setUserTenantMemberId(accountUserExtBean.getUserTenantMemberId());
            projectMemberRoleRelation.setUserId(projectMsg.getCreatorId());
            projectMemberRoleRelation.setRoleId(RoleEnum.PROJECT_OWNER.getRoleId());
            projectMemberRoleRelation.setMemberType(ProjectMemberType.SPACE_MEMBER.getValue());
            projectMemberRoleRelation.setMemberName(userLoginBO.getNickName());
            projectMemberRoleRelation.setMemberAvatar(userLoginBO.getPortrait());
            projectMemberRoleRelation.setPhone(userLoginBO.getPhone());
            projectMemberRoleRelation.setStatus(WorkspaceMemberRoleRelationStatusEnum.NORMAL.getStatus());
            projectMemberRoleRelation.setGmtLastActive(new Date());
            projectMemberRoleRelation.setGmtJoin(new Date());
            projectMemberRoleRelation.setGmtInvite(new Date());
        projectMemberRoleRelation.setDelStatus(AssetsDelStatusEnum.NORMAL.getStatus());
    
            projectMsgMapper.insert(projectMsg);
            projectMemberMapper.insert(projectMember);
    
            return projectMsg;
        }

    Although the code logic is not complicated, but looking at such a large amount of code, you will definitely lose the mood to read it.

  2.  The code we write is mainly for reading. The binary file after the code is compiled is for the machine to execute. Therefore, when we write code, we should organize the language well and have clear logic like writing an article. Don’t write hundreds of lines at once, so that people will not know what they are writing.

  3. As for what is good code, I think that on the basis of function realization, the code that is easier for people to read and understand is good code. It is best to let people look at your main function, so that they can know what you want to do, and divide it into several parts to complete it. Here I most appreciate the refresh method in the spring source code, which describes the complex container refresh process clearly and clearly with a dozen lines of code: 

    	@Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) { 
    
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
     
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
    
    				// Register bean processors that intercept bean creation.
    				registerBeanPostProcessors(beanFactory); 
    
    				// Initialize message source for this context.
    				initMessageSource();
    
    				// Initialize event multicaster for this context.
    				initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
    				onRefresh();
     
                    // Check for listener beans and register them.
    				registerListeners();
     
    				finishRefresh();
    			} catch (BeansException ex) { 
    				destroyBeans();
    				cancelRefresh(ex); 
    				throw ex;
    			} finally { 
    				resetCommonCaches();
    				contextRefresh.end();
    			}
    		}
    	}

    I won't go into too much detail about the spring source code here. What we are going to learn is the way it organizes the code.

        Code authors should try their best to write code that is easy to understand. We want to write the code so that others can see it at a glance without having to study it exhaustively.

2. What is clean code

There is no one-size-fits-all answer to what defines clean code.

The author of "clean code" quotes a few passages in the book: 

我喜欢优雅而高效的代码。代码逻辑应当直接了当,让缺陷难以隐藏;尽量减少依赖关系,使之便于维护;
依据某种分层战略完善错误处理代码;性能调至最优,省得引诱别人做没规矩的优化,搞出一堆混乱出来。
整洁的代码只做好一件事。
我可以列出我留意到的整洁代码的所有特点,但其中有一条根本性的,整洁的代码总是看起来像是某位
特别在意它的人写的,几乎没有改进的余地。代码的作者什么都想到了,如果你企图改进它,总会回到
原点,赞叹某人留给你的代码---全身心投入的某人留下的代码。

Summarized the author's standards for clean code: elegant, caring, no code duplication, improved expressiveness, early construction of simple abstractions

3. Meaningful naming

When I first started learning programming, I was told to name variables well. I think it’s not enough just to know the name, but the naming should be concise and easy to understand. For variables with the same meaning, the naming in different functions and entities should be as uniform as possible.

3.1 True to the name

I think most programmers know that variable naming should be worthy of the name, but how many people are willing to spend time and energy to do this. Picking a good name takes time, but the time saved later will be more than the time spent here.

The name of a function, variable, or class should tell you why it exists, what it does, and how it should be used. If the name has to be supplemented by comments, it is not worthy of the name.

3.2 Avoid misleading

For example: If a variable is not of type List, do not use ***List to name the variable

Beware of using names with minor differences: like XYZControllerEfficientHandingOfString and ZYZControllerForEfficientStorageOfString, it takes a little while to see the difference between the two words.

3.3 Making meaningful distinctions

1. In order to meet the needs of the compiler and interpreter, we often distinguish between the names of two different variables in the same scope with numbers ending, such as: 

 Such a distinction has no meaning for the understanding of variables, but only for the understanding of the code through the compiler and interpreter. We can modify the variable name according to the source or role of the two variables: 

In this way, we can know one is the added project list information, and the other is the created project list information.

2. Bullshit is another distinction that doesn't make sense. For example, the three variable names of product, productInfo and productData have no difference in the sense of representation. Same for function names: 

With the above three function names, it is impossible to distinguish which function to call. 

3.4 Use readable, common, simple names

3.5 Avoid coding

3.6 Class names -- class names should not be verbs

3.7 Method Names -- Method names should be verbs or verb phrases

3.8 No puns 

Avoid using the same word for different purposes. The same term is used for different concepts, which is basically a pun.

3.9 Using the name of the solution domain

Only programmers will read our code, so try to use computer science terms, algorithm names, schema names, etc.

3.10 Use the name of the problem area in question

If it is not possible to use terms familiar to programmers, you can use the technical terminology of the problem domain involved.

3.11 Add meaningful context

Most names are not self-explanatory. We need to provide well-named classes, functions, or namespaces to prevent names and provide context to readers. If there is still no description, you need to add a prefix to the name for description.

Suppose there are a bunch of variables: firstName, lastName, street, city, state, zipCode, etc. These variables together can be used to describe an address information. But if a single variable appears in a function, such as state appears alone, we cannot be sure whether the state here represents part of the address information, or something else. In this case, the prefixes addrState, addrFirstName, addrLastName, etc. can be added to provide context description.

3.12 Don't add useless context

Guess you like

Origin blog.csdn.net/zhoushimiao1990/article/details/122669292