Code Concise 1 - ¿Qué es el código conciso y la denominación significativa?

        Recientemente, me uní a una empresa nueva con un pequeño equipo. Después de trabajar durante un período de tiempo, descubrí que la situación del código en el equipo era muy mala. El equipo tiene un total de dos líneas de productos y cinco desarrolladores. Cada uno tiene un estilo de código. Es comprensible que cada persona tenga su propio estilo de código. Los cambios en los requisitos pueden ser catastróficos. Así que planeo volver a leer un libro "The Way of Clean Code" que leí hace unos años - el nombre en inglés es "clean code", también para no desviarme.

1. Primero piense en algunas preguntas:

  1. ¿Qué leemos de código? ?
  2. ¿Cuál es el propósito del código que escribimos? ?
  3. ¿Qué es un código bueno y qué es un código malo? ?

Aquí están mis pensamientos sobre estas tres preguntas:

  1.  Cuando leemos el código de otra persona, lo primero que necesitamos saber es qué hace ese código o función, y segundo, para completar la función de la función, en qué pasos se divide, y finalmente los pasos específicos de estos pasos. detalle. Por ejemplo, el siguiente código: 
        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;
        }

    Por el nombre de la función, podemos saber que el método consiste en agregar datos del proyecto, y su implementación se divide en tres pasos: verificar la legalidad de los parámetros, compilar información del proyecto, información del miembro del proyecto Hou Jian y, finalmente, agregar datos. Si juntamos todas las implementaciones del método, este es el siguiente código: 

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

    Aunque la lógica del código no es complicada, pero al ver una cantidad tan grande de código, definitivamente perderá el ánimo para leerlo.

  2.  El código que escribimos es principalmente para leer. El archivo binario después de compilar el código es para que la máquina lo ejecute. Por lo tanto, cuando escribimos código, debemos organizar bien el lenguaje y tener una lógica clara como escribir un artículo, no escribir cientos de líneas a la vez, para que la gente no sepa lo que está escribiendo.

  3. En cuanto a lo que es un buen código, creo que, sobre la base de la realización de funciones, el código que es más fácil de leer y comprender para las personas es un buen código. Lo mejor es dejar que la gente mire tu función principal, para que puedan saber lo que quieres hacer, y dividirla en varias partes para completarla. Aquí aprecio más el método de actualización en el código fuente de Spring, que describe el complejo proceso de actualización del contenedor clara y claramente con una docena de líneas de código: 

    	@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();
    			}
    		}
    	}

    No entraré en demasiados detalles sobre el código fuente de Spring aquí. Lo que vamos a aprender es la forma en que organiza el código.

        Los autores de código deben hacer todo lo posible para escribir un código que sea fácil de entender. Queremos escribir el código para que otros puedan verlo de un vistazo sin tener que estudiarlo exhaustivamente.

2. ¿Qué es el código limpio?

No existe una respuesta única a lo que define un código limpio.

El autor de "código limpio" cita algunos pasajes del libro: 

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

Resumió los estándares del autor para un código limpio: elegante, cuidadoso, sin duplicación de código, expresividad mejorada, construcción temprana de abstracciones simples.

3. Denominación significativa

Cuando comencé a aprender programación, me dijeron que nombrara bien las variables. Creo que no es suficiente solo saber el nombre, sino que la denominación debe ser concisa y fácil de entender.Para variables con el mismo significado, la denominación en diferentes funciones y entidades debe ser lo más uniforme posible.

3.1 Fiel al nombre

Creo que la mayoría de los programadores saben que la denominación de variables debería ser digna de ese nombre, pero cuántas personas están dispuestas a dedicar tiempo y energía para hacer esto. Elegir un buen nombre lleva tiempo, pero el tiempo que se ahorre más adelante será mayor que el que se dedique aquí.

El nombre de una función, variable o clase debe decirle por qué existe, qué hace y cómo debe usarse. Si el nombre tiene que ser complementado con comentarios, no es digno del nombre.

3.2 Evitar engaños

Por ejemplo: si una variable no es del tipo Lista, no use ***Lista para nombrar la variable

Tenga cuidado con el uso de nombres con diferencias menores: como XYZControllerEfficientHandingOfString y ZYZControllerForEfficientStorageOfString, toma un poco de tiempo ver la diferencia entre las dos palabras.

3.3 Hacer distinciones significativas

1. Para satisfacer las necesidades del compilador y del intérprete, a menudo distinguimos entre los nombres de dos variables diferentes en el mismo ámbito con números que terminan, como: 

 Tal distinción no tiene sentido para la comprensión de las variables, sino sólo para la comprensión del código a través del compilador y el intérprete. Podemos modificar el nombre de la variable según la fuente o rol de las dos variables: 

De esta manera, podemos saber que uno es la información de la lista de proyectos agregados y el otro es la información de la lista de proyectos creada.

2. Bullshit es otra distinción que no tiene sentido. Por ejemplo, los tres nombres de variables de producto, productInfo y productData no tienen ninguna diferencia en el sentido de representación. Lo mismo para los nombres de funciones: 

Con los tres nombres de funciones anteriores, es imposible distinguir a qué función llamar. 

3.4 Use nombres legibles, comunes y simples

3.5 Evite codificar

3.6 Nombres de clase: los nombres de clase no deben ser verbos

3.7 Nombres de métodos: los nombres de métodos deben ser verbos o frases verbales

3.8 Sin juegos de palabras 

Evite usar la misma palabra para diferentes propósitos. El mismo término se usa para diferentes conceptos, lo que básicamente es un juego de palabras.

3.9 Uso del nombre del dominio de la solución

Solo los programadores leerán nuestro código, así que trate de usar términos informáticos, nombres de algoritmos, nombres de esquemas, etc.

3.10 Utilizar el nombre del área problemática en cuestión

Si no es posible usar términos familiares para los programadores, puede usar la terminología técnica del dominio del problema involucrado.

3.11 Agregar contexto significativo

La mayoría de los nombres no se explican por sí mismos. Necesitamos proporcionar clases, funciones o espacios de nombres bien nombrados para evitar nombres y proporcionar contexto a los lectores. Si todavía no hay una descripción, debe agregar un prefijo al nombre para la descripción.

Supongamos que hay un montón de variables: nombre, apellido, calle, ciudad, estado, código postal, etc. Estas variables juntas se pueden usar para describir una información de dirección. Pero si una sola variable aparece en una función, como el estado aparece solo, no podemos estar seguros de si el estado aquí representa parte de la información de la dirección o algo más. En este caso, se pueden agregar los prefijos addrState, addrFirstName, addrLastName, etc. para proporcionar una descripción del contexto.

3.12 No agregue contexto inútil

Supongo que te gusta

Origin blog.csdn.net/zhoushimiao1990/article/details/122669292
Recomendado
Clasificación