大学毕业4年-回顾和总结(6)-技术研发-重构之法

大部分的公司,开发项目都是作坊式的,没有产品和项目的需求分析,进而做出技术架构和详细设计。

很多人,听到上级和老板的一个想法,就开始写代码,边写边改,甚至推倒重来。

最终,导致的常见结果之一,项目代码混乱,新员工甚至老员工,对项目理解比较吃力。

如果你去改造代码,改好了,没有任何功劳。改出问题了,领导、测试、产品,很可能会说你不行。

这一点,是让很多程序员纠结的地方。

我个人还是倾向重构的,先熟悉项目总体环境,从易到难。

项目开发,从外部看,就是一个个的功能。

从内部看,不就是一个个函数和API吗。

只要输入和输出是稳定的,就不会出现重大的失误,导致牵一发动全身的不良后果。

下面记录一些,我个人自己揣摩的一些重构方法,阅读《重构》这本书,也带给了我一些启发。

1.命名规范化

包名、类名、方法名、变量名,取合适的英文单词。

比如在一个电商项目中。

包名:com.company.shop.front.controller,前端系统的控制层

类名:OrderController,处理订单的控制器

方法名:findById,根据id查找对象,我个人更喜欢用get。

变量名:List<String> memberIdList = new ArrayList<String>();

会员id的list集合

比较坑的命名:Object tagcode = map.get("tagCode");

变量命名,没有按照Java驼峰式命名规范来写,“tagcode”和“tagCode”竟然同时存在。

在Java内部代码变量名,如果错了还有提示,在Freemarker和JSP等界面中,字符串的值,用错了,根本没有提示。

大小写不统一的bug,还很难发现。

命名要一致:Controller、Service、Dao等,同一个人和不同人的,尽可能遵循一定的标准,阅读和修改其他人代码也更顺利。

2.代码合理组织

controller:控制器,响应请求,路由控制

service:服务层,处理业务逻辑

dao:数据访问层

model:数据库模型

bean:内部用的实体类

util:工具代码

interceptor:拦截器

其它代码,可以按照功能等进行划分,让人一眼望去,就知道这个包下的代码,大致做了什么事情。

3.项目合理组织

合理拆分项目:

移动端,mobile项目

Web前端,front项目

后端管理:backend项目

合理服务拆分:

商品服务系统:ProductService项目

会员服务系统:UserService项目

登录服务系统:LoginService项目

订单服务系统:OrderService项目

公共代码:Model模型、Util工具类

听说淘宝和京东的电商网站,有几百上千个服务。

4.使用最小最恰当的作用域

类,大多数类用的是public,public class ProductService,如果只是在包内部使用,可以去掉public。

字段,尽可能用private, private ProductService productService。如果需要,通过get和set方法,来获得和修改值。

方法/函数,对外被调用的用public,只在类的内部使用的,尽可能用private。

   public void  add(){
      doAdd();
   }

   private void doAdd(){

   }

很多人,内部代码都搞成public,乍一眼看上去,还以为外部有调用。

必须得看看依赖,才确定。

对外暴露了过多的接口,不该被调用的被调用了。

5.常量提取

"success",把作用一致并且相同的字符串,提取成常量,统一管理。

其中一种方式:

public class FrontConst {

	public static final String COOKIE_LOGINNAME = "loginNameCookie";

	public static final String COOKIE_PASSWORD = "passWordCookie";

}

6.重复代码提取和封装

业务代码,提取成私有方法,内部重复使用。

工具代码,提取到工具类中,可以复用,比如日期处理、把list转换成map。

 public class BizUtil {
	/**
	 * 把1个集合,转换成Map。用法示例:Map<String, Dictionary> dictionaryMap = BizUtil.listToMap("BIANMA", dictionarys);
	 * @param keyName 集合元素唯一字段的名称
	 * @param list 集合元素
	 * @return map
	 */
	public static <K, V> Map<K, V> listToMap(final String keyName, List<V> list) {
		if(CollectionUtils.isEmpty(list)){
			return null;
		}
		return Maps.uniqueIndex(list, new Function<V, K>() {
			@Override
			public K apply(V v) {
				try {
					return (K)PropertyUtils.getSimpleProperty(v, keyName);
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					e.printStackTrace();
					return null;
				}
			}
		});
	}

	/**
	 * 把1个集合,转换成Map。用法示例:Map<String, Dictionary> dictionaryMap =
	 * BizUtil.listToMap(String.class, Dictionary.class, "BIANMA", dictionarys);
	 *
	 * @param k
	 *            Map的key的class
	 * @param v
	 *            Map的value的class,集合list元素的类型
	 * @param keyName
	 *            集合元素唯一字段的名称
	 * @param list
	 *            集合元素
	 * @return map
	 */
	//这种方式,废弃了,需要多传2个参数
	public static <K, V> Map<K, V> listToMap(Class<K> k, Class<V> v,
			String keyName, List<V> list) {
		Map<K, V> map = Maps.newHashMap();
		if (CollectionUtils.isNotEmpty(list)) {
			for (V val : list) {
				try {
					PropertyDescriptor pd = new PropertyDescriptor(keyName, v);
					Method getMethod = pd.getReadMethod();// 获得get方法
					Object o = getMethod.invoke(val);// 执行get方法返回一个Object
					if (o != null && o.getClass().equals(k)) {
						map.put((K) o, val);
					}
				} catch (IllegalAccessException | IllegalArgumentException
						| InvocationTargetException | IntrospectionException e) {
					e.printStackTrace();
				}

			}
		}
		return map;
	}

7.函数拆分

1个函数,有5个参数,有2种不同的使用场景。

同一个函数完成了2件不同的事情。

void add(int a,int b,int c);

换成

void addOrder(int a,int b);

void addProduct(int c)。

8.函数合并

2个函数,完成了类似的事情,简化成1个,

函数是拆分,还是合并,要具体分析。

9.单一职责原则

一个项目、一个模块、一个类、一个函数,完成一件事。

如果完成了多件事,需要进行拆分成多个独立的函数,至少内部需要进行拆分。

比如:

void add(int a,int b,int c)

可以拆分成

void add1(int a,int b)和void add2(int c)

也可以拆分成

void add(int a,int b,int c){

add1(a,b);

add2(c);

}

10.控制类和函数的行数

一个类,如果函数太多,往往是承载了太多的功能。

把不紧密相关的功能,堆积在了一起。

一个方法,如果代码超过了100行,存在问题的可能性就增大了很多。

在我自身的经历中,很多同事的函数,只要超过100行,一眼望去就能发现问题。

另外,函数代码过多,修改bug和新增业务逻辑的时候,很容易引入新的问题。

因此,函数拆分、降低作用域,可以保证过去稳定的代码逻辑,不会有改动。

11.提前返回

先检查错误,如果有问题,直接返回,以免嵌套过深。

public String add(){
		Member member = this.getMember();
		if(StringUtils.isBlank(...){
			return error("地址信息有误!");
		}
}

经常出现下面的情况

if(...){

if(...){

if(...){

}

}

return ...;

12.定义枚举

枚举是常量的进一步封装。

public enum OrderPayStatusEnum {
	NO("0", "未支付"), YES("1", "已支付");

	private String code;
	private String remark;

	OrderPayStatusEnum(String code, String remark) {
		this.code = code;
		this.remark = remark;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public static String getPayStatus(String code){
		if(StringUtils.isEmpty(code)){
			return null;
		}
		if(code.equals(NO.getCode())){
			return NO.getRemark();
		}else if(code.equals(YES.getCode())){
			return YES.getRemark();
		}
		return null;
	}
}

13.统一API交互接口

后端和移动端,后端和Web前端的交互,都是Result的json字符串。

后端,所有请求,统一都是返回Result。

public class Result {

private Integer code;

private String desc;

private Object data;

}

多人开发的时候,如果没有架构师之类的角色,各自为战,真是乱套。

14.模块化和依赖

大多数项目,都会有诸如邮件、短信验证码、登录服务、图片云服务等。

把配置文件单独拿出来,可以手动通过Spring的配置文件,配置bean。

如果需要,引入配置文件,不引入,代码也不会报错。

spring-mail-config.xml

<context:property-placeholder location="file:${config_path}/config/mail.properties" ignore-unresolvable="true" />
  <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host" value="${mailServerHost}" />
		<property name="port" value="${mailServerPort}" />
		<property name="javaMailProperties">
			<props>
				<prop key="mail.smtp.auth">true</prop>
				<prop key="mail.smtp.timeout">25000</prop>
			</props>
		</property>
		<!-- 发送者用户名 -->
		<property name="username" value="${mailUserName}" />
		<!-- 发送者密码 -->
		<property name="password" value="${mailPassword}" />
		<property name="defaultEncoding" value="UTF-8" />
	</bean>

	<bean id="mailClientServer" class="com.shop.common.mail.MailClientServer">
		<property name="javaMailSender" ref="javaMailSender" />
		<property name="configuration" ref="freeMarkerConfigurationFactory" />
		<property name="mailFromAddress" value="${mailFromAddress}" />
	</bean>

还比如,咱们的图片用的阿里云的OSS。

统一封装。

配置文件

oss.properties

oss.xml

   	<context:property-placeholder
		location="file:${config_path}/config/oss.properties"
		ignore-unresolvable="true" />
	<bean id="ossConfig" class="com.shop.common.oss.OssConfig">
		<property name="endpoint" value="${oss.endpoint}" />
		<property name="bucketName" value="${oss.bucketName}" />
		<property name="accessKeyId" value="${oss.accessKeyId}" />
		<property name="accessKeySecret" value="${oss.accessKeySecret}" />
		<property name="imgDomain" value="${oss.imgDomain}" />
		<property name="fileDomain" value="${oss.fileDomain}" />
	</bean>

Java代码

public class OssUtil {}

15.代码复用

代码复用,是一个广泛的话题。

前文提到的枚举、常量、函数拆分,目的之一就是为了方便代码复用。

一个优秀的程序员,抵得上十个差的程序员,其中一个原因就是“代码复用多”。

总是写重复的代码,把程序员这个智力密集型工作,干成了体力密集型,早晚被累死。

梳理业务需求、做好业务方面的架构设计。

另外,技术方面的架构设计,完全掌握在技术人员手中,对业务的依赖不大。

开发一个功能时,先想好思路,技术方案,再写代码。

架构复用、设计复用、工具类、枚举、常量。

另外还有一种,非常常见的,流程复用。

前端系统:

1.构造url和参数

2.执行请求,获得数据

3.根据状态码,执行不同的操作

4.正常状态,渲染数据,或执行动作

移动端:

流程类似

后端:

1.稳定并且统一的API接口

2.业务逻辑封装

无论内部怎么变,接口稳定,就不会影响Web前端和移动端。

在合适的时机,内部项目拆分,项目服务化。

重构的技巧,还是有很多的,更多还是看个人对编程的理解。

对于有经验的程序员来说,《重构》是一本不错的书,可以用来快速加深平时对项目代码的梳理。

对于新手来说,《重构》和设计模式,这种书,受益偏小。

小雷-一个有独立见解的年轻人
2016年4月16日~清明节刚过,五一又要来了
湖北-武汉~听说最近有几条公交专线要开通了

最近,有好多好多的想法和话题要写,时间不太够。
更准确来说, 时间是有的,写文章,也要看心情。
写一篇严肃一点的长篇大论,一般都需要1小时以上。
在写作之前,大脑里面一直在不断地“打草稿”,写的过程中,需要不断发散,要有条理,还要严谨,站得住脚。

一些问题的根源,也许是我的身价还是太低了,更多时间忙着搞钱,一些有价值的事情,只能慢慢地去做。

时间: 2024-11-05 14:37:17

大学毕业4年-回顾和总结(6)-技术研发-重构之法的相关文章

大学毕业4年-回顾和总结(1)-钱,金钱观

友情提示大学毕业4年-回顾和总结系列文章,会比较多.感兴趣的同学,需要一点耐心.爆料和精华,需要一点时间. 男人的责任毕业了,挣钱是最基本的事情了. 每个人都需要挣钱,养活自己,养活家人.一人吃饱,全家不饿,这种日子,早晚会过去的. 尤其是男性,通常是家庭主力,必须一直奋斗. 工作不仅仅是搞钱 由于某些情况,长时间连续玩得多了,闲暇时间多了,突然真正体会到,人很多时候工作也不完全是为了搞钱. 有个事干,精神也容易维持在一种稳定的状态.大起大落,不能是常态.游手好闲,无事生非,真是好有道理. 想快

大学毕业4年-回顾和总结(2)-钱,收入和支出

过年回家,长辈最喜欢问两件事.第一件事,谈朋友没有啊.第二件事,现在一个月搞多少钱.     如果你和他们说,一个月工资是1万,那么他们立刻认为,你现在手上应该有十多万了.     上班族听了,心里咯噔一下. 收入多少和节余多少完全是两个概念,通常来说,收入决定了你节余的最高上限,但不能保证保证的节余下限.      长辈们考虑收入,完全是参考他们的"生活体系",吃喝住基本不花钱,很少买衣服,也没有五险一金等乱七八糟的概念. 工作4年,感觉没怎么乱花,也没攒到几个钱,现在还欠了一屁股债

大学毕业4年-未来展望-序

再过3个月,就毕业四年了.    It's so fast...我只想说~ 大学毕业4年-回顾和总结 系列,更多是对过去四年的总结.仔细想了想,未来打算还是单独写个系列比较妥当.    就名为"大学毕业四年-未来展望"吧~ 随着时间的流逝, 越来越多的事情越来越更加明确了. 有些事情,你一旦选择了,就难以回头.甚至可以说,你很害怕回头看. 对,就向前看. 有的事情,错的再多,失败得再惨,总有崛起之日. 对于未来,最重要的事情:婚姻家庭. 职业发展.人生价值.社交交友.读书学习. 婚姻家

【乔布斯05年斯坦福大学毕业典礼上的演讲】——Stay Hungry, Stay Foolish.(转)

Steve Jobs: Commencement Address at Stanford University "Stay Hungry, Stay Foolish." 求知若饥,虚心若愚 史蒂夫·乔布斯(Steve Paul Jobs)苹果电脑公司和皮克斯动画公司(Pixar)首席执行官. 以下是Steve Jobs在2005年6月12日斯坦福大学毕业典礼上的演讲. Thank you.I'm honored to be with you today for your commenc

小雷郑重承诺:在2017年之前,对大学毕业4年以来的所有努力和探索,做一个全面客观的总结,技术研究、工作创业、投资理财、朋友感情等

又是新的一年,祝各位上班族,开工大吉.祝各位朋友,身体健康,开开心心赚钱过日子. 回家过了12天,经历了一些事情,放佛过了好久好久,有几年的样子. 回首过去,惨惨的,真的很惨.一点拿得出手的成绩和成就都没有,太让自己失望了. 过去的2014和2015,混的确实太惨,我都不好意思去写总结.很多计划没实现,夭折的故事也太多了.总之,过去不敢去回顾. 2016年又正式开始了,有些感慨.现在还不方便,对过去"盖棺定论" .希望,在2017年之前,能有一个认真的回顾和总结. 坦诚地面对过去的探索

一个计算机学院学生大学学习生活的回顾与反省(转)

一个计算机学院学生大学学习生活的回顾与反省 http://club.youshang.com/ysbbs/viewthread.php?tid=12941 推荐语: 每年的6.7月份,是大四学生毕业离校的时候.在这段时间的前后,很多毕业生都会写写文章总结四年大学生活.无论是分享成功的喜悦,还是反思四年的得与 失.套用一句名言,成功的经历大多是相同的,失败的却有各自的不幸.师兄师姐的"牢骚"."分享",也许给大多数人一时的激情,最后,可以笑看大学四年的 并不多.于是,

乔布斯2005年斯坦福大学毕业演讲(中文)

2005年6月14日,苹果CEO史蒂夫•乔布斯(Steve Jobs)在他的母校斯坦福大学的毕业典礼发表了著名的演讲,关于这段演讲,你会看到N多人的推荐(比如同样喜欢在大学演讲的李开复先生).此前曾经发过中文字幕版的乔布斯斯坦福大学演讲视频,今天补上中英文对照版的乔布斯演讲稿,里面有很多经典语句,值得反复阅读. I am honored to be with you today at your commencement from one of the finest universities in

大学毕业必须知道的东西:三方协议、报到证(派遣证)、干部身份

[档案问题] 毕业之前必看的东西-你自己的档案问题,详细至极真正能证明你学习经历的就是你的档案.档案里面有你各个时期的学籍卡.成绩单.各方面的评语.获奖证明.还有你的党团材料.这些都是原始材料,不可复制. 档案虽然"光辉不再",但并不等于是随处可丢弃的"鸡肋", 专家建议:应届生应关心自己的档案,免得未来不必要的麻烦. [档案与工龄] 很多大学毕业生找到工作后,没有及时办理参加工作手续,工作几年后仍然是学生身份,从而影响了自己的转正定级,也影响到工龄和退休金的计算.

三年回想——大学毕业工作后的感悟

从2012年9月到2016年1月,从大学毕业到现在就业,已经有3个多年头了.在这三个多年头里自己学到了不少的东西,也明白了一些做人的道理 我的大学是一个一点儿也不知名的专科院校,落后的环境.师资.教育.思想.让我在大学里没有学到太多的东西,说这些并不是来贬低我的母校有多差,自己有多差劲,而是去反思.去思考.去弥补.在大学里,我发现我除了读书什么也不会,而且读的还不是多好.从出生到现在我家务活拿起手指我都能算清.眼看自己也快是要成家的人了,自己却还懵懵懂懂,像一个孩子一样.老实说,我也想早点成家,