精华内容
下载资源
问答
  • 项目重构方案模板、项目重构方案模板ppt,项目重构方案计划模板
  • 项目重构

    2020-11-12 11:06:58
    一、项目重构的几个步骤 1.再次了解业务 在重构之前再次了解业务,了解需求。从需求的角度,找出项目不合理的地方,从需求发展的角度,规划好项目需要预留的东西。 2.再次了解技术 对于不熟悉的技术,再次了解...

    一个项目:如果一开始设计的不够好,或者用的是不熟悉的技术,或者需求不断改变。最终这个项目都会走向混乱,无法进行下去,或者是很小的变动都需要花费很大的力气。如果恰好这三个都遇到了,那么这个项目必将是一片混乱。这时候需要下很大的决心重构项目,理清、理顺整个项目,使项目更具有生命力。

    一、项目重构的几个步骤

    1.再次了解业务

    在重构之前再次了解业务,了解需求。从需求的角度,找出项目不合理的地方,从需求发展的角度,规划好项目需要预留的东西。

    2.再次了解技术

    对于不熟悉的技术,再次了解技术,分析项目中技术使用的是否合理,是否有更好的办法。

    3.分析现有项目

    对现有项目全面梳理,取其精华、去其糟粕。着重分析数据方面的问题。确定项目需要推倒重来式的重构,还只需要部分重构。

    4.重构规划

    需求分析,技术分析。项目设计,时间安排。

    5.重构及总结

    进行项目重构,继续维护原有项目。总结技术和业务。

    二、项目重构的意义

    1.可持续发展

    一个混乱的项目,重构是让项目活下去的最好的办法,也是比较痛苦的一个办法,需要极大的毅力和决心。一般人还是喜欢缝缝补补,凑合下去。重构后项目增加新的需求和有一些变动的时候改起来也容易了。

    2.自我提升的意义

    通过重构项目可以再次回顾整个项目,复盘整个项目,用更好的办法重新构建项目,是对技术的一个很好的提升。

    三、项目重构需要克服的困难

    展开全文
  • 主要介绍了浅谈vue项目重构技术要点和总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 项目重构方案设计

    2021-02-21 13:23:54
    最近接手到一个已经成型的项目,然后我们的任务就是对它进行重构,这个项目是一个功能很齐全的WPF视频播放器(附带很多其他功能),在仔细研究了项目的背景和架构以后,初步做出了一下的重构方案:目前现状:虽然...
  • 项目重构的一些思考与经验总结

    千次阅读 2018-10-09 23:50:14
    项目重构的一些思考与经验总结项目重构的一些思考与经验总结蹩脚之处功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定...

    项目重构的一些思考与经验总结

    要么爬过坑走过弯路,要么用脑子思考。看你如何选择?

    那年那月那样的我

    还依稀记得刚出道不久的自己照葫芦画瓢的写着代码,不知道为什么要这么写,更无从说这样写的好处与坏处了,从网上复制粘贴,实现了功能就不管了,这也是大部分码农干的话吧。那段时间虽然在经验上积累了一些,但是在技术上没有从心底的去领悟一些东西,没有思考,更没有尝试着去创新。吃了亏才知道改,走了弯路知道接下来的每一步都要谨慎,都要用心。

    悟性决定成长

    你能悟多少,你才能成长多少。跑偏了,回归正题。今年来,到这家公司没有什么新颖的技术,技术体系基本上是 ant + spring + mybaits + mysql + bootStrap + html + js。也由于我负责的这几个项目进度要求不是很紧急,所以有时间去研究项目的架构,代码优化,重构等,抛弃以前蹩脚的编程方式。

    哪里让我感到蹩脚

    1、每每遇到异常时,不知道是抛出还是处理,要怎么处理,没有一个很理性的认识,处理异常总是凭感觉看心情。
    2、日志的打印问题,打多了不好,打少了也不好,甚至出现打了很多日志,但是出错时发现没有打印相关信息。时常看到有代码基本上有一半的篇幅是日志,很不雅观。
    3、Controller层接口返回五花八门问题,这我也是醉了,负责重构的这个项目返回值有Map,List,Void还有封装的resultBean 两三种。这样前端处理对应着也就五花八门了。
    4、大小写不统一问题,这个是重构最头疼的一个问题。举个栗子,在使用Mybaits时候,有时候查询结果直接封装的对象里,有时候省懒直接用Map封装,问题来了,对象封装返回字段名转变成了驼峰法,Map直接是查询的字段名,这样混着来,查问题很费解。
    5、Ajax没有进行统一封装问题。一般不会有太大问题,但是,因为Ajax是局部刷新,所以不能进行页面跳转的操作,在Session过期跳转登录页面上如果不对Ajax统一封装,那就尴尬了。

    总结的处理方式

    AOP统一处理异常并打印日志

    AOP日志辅助

    统一ResultBean

    直接上代码

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.f2f.voi.common.CommonContainer;
    
    @Component
    public class BaseInterceptor {
    	
    	@Autowired
    	protected CommonContainer commonContainer;
    	
    	protected static final Logger logger = LoggerFactory.getLogger(BaseInterceptor.class);
    
    	protected boolean isContainAnnotationName(JoinPoint pjp, String name) {
    		Signature signature = pjp.getSignature();    
    		MethodSignature methodSignature = (MethodSignature)signature;    
    		Method targetMethod = methodSignature.getMethod();
    		Annotation[] annotations = targetMethod.getAnnotations();
    		for(int i = 0; i < annotations.length; i++){   
    			Annotation annotation = annotations[i];
    			if(annotation.annotationType().getName().contains(name))
    				return true;
    	    }
    		return false;
    	}
    }
    
    
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    
    /**
     * @describe 日志打印控制
     * @author YoungSmith
     * @date 2018年6月14日 下午2:14:06
     */
    @Aspect
    @Component
    public class LogInterceptor extends BaseInterceptor {
    	
    	private static final Boolean isLogPretty = false;
    	
    	@Pointcut("execution(public * com.f2f.voi.*.controller.*.*(..))")
    	public void myMethod() {
    	};
    
    	/**
    	 * 前置通知:在某连接点之前执行的通知,但这个通知不能阻止连接点前的执行
    	 * 
    	 * @param jp
    	 *            连接点:程序执行过程中的某一行为
    	 */
    	@Before("myMethod()")
    	public void before(JoinPoint jp) {
    		String method = jp.getTarget().getClass().getName() + "." + jp.getSignature().getName();
    		StringBuilder message = new StringBuilder(method + "() started.");
    		logger.info(message.toString());
    		
    		if(methodHasNonAopLogAnnotation(jp)){ // 方法上有不打印日志注解
    			return;
    		}
    		
    		List<Integer> list = getNonAopLogParamsIndexs(jp);
    		 
    		Object[] args = jp.getArgs();
    		StringBuilder logStr = new StringBuilder(method + "'s param is [");
    		for (int i = 0; i < args.length; i++) {
    			try {
    				if(list.contains(i))
    					continue;
    				logStr.append(JSONObject.toJSONString(args[i], isLogPretty) + ",");
    			} catch (Exception e) {
    				// do nothing
    			}
    		}
    		logStr.deleteCharAt(logStr.length() - 1);
    		logStr.append("]");
    		logger.info(logStr.toString());
    	}
    
    	/**
    	 * 获取方法中没有NonAopLog注解的参数的下标列表
    	 * @param jp
    	 * @return
    	 */
    	private List<Integer> getNonAopLogParamsIndexs(JoinPoint jp) {
    		MethodSignature signature = (MethodSignature) jp.getSignature();
    		Method methodObj = signature.getMethod();
    		Annotation[][] parameterAnnotations = methodObj.getParameterAnnotations();
    		List<Integer> list = new ArrayList<>();
    		outer: for(int i = 0; i < parameterAnnotations.length; i++){
    					Annotation[] annotations = parameterAnnotations[i];
    					for(int j = 0; j < annotations.length; j++){
    						Annotation annotation = annotations[j];
    						if(annotation.annotationType() == NonAopLog.class){
    							list.add(i);
    							continue outer;
    						}
    					}
    				}
    		return list;
    	}
    
    	@After("myMethod()")
    	public void after(JoinPoint jp) {
    		String logStr = jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " finished.";
    		logger.info(logStr);
    	}
    
    	/**
    	 * 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行。
    	 * 类似web中Servlet规范中Filter的doFilter方法。
    	 * 
    	 * @param pjp
    	 *            当前进程中的连接点
    	 * @return
    	 */
    	@Around("myMethod()")
    	public Object doAround(ProceedingJoinPoint pjp) {
    		long time = System.currentTimeMillis();
    		Object result = null;
    		String logStr = pjp.getTarget().getClass() + "." + pjp.getSignature().getName();
    		try {
    			result = pjp.proceed();
    		} catch (BusinessException e) {
    			logger.info(logStr + " has BusinessException. {}", e.toString());
    			return ResultUtil.fail(e.getErrorCode(), e.getErrorMessage(), e.getErrorData());
    		} catch (BaseException e) {
    			logger.error(logStr + " has BaseException. The Error Message is:", e);
    			return ResultUtil.fail(Constants.SYSTEM_ERROR, commonContainer.getMessage(Constants.SYSTEM_ERROR));
    		}  catch (Exception e) {
    			logger.error(logStr + " has Exception. The Error Message is:", e);
    			return ResultUtil.fail(Constants.SYSTEM_ERROR, commonContainer.getMessage(Constants.SYSTEM_ERROR));
    		} catch (Throwable e) {
    			logger.error(logStr + " has Throwable. The Error Message is:", e);
    			return ResultUtil.fail(Constants.SYSTEM_ERROR, commonContainer.getMessage(Constants.SYSTEM_ERROR));
    		}
    		logger.info(logStr + " Execution Time is:" + (System.currentTimeMillis() - time)/1000.00d + "s");
    		return result;
    	}
    	
    	private boolean methodHasNonAopLogAnnotation(JoinPoint pjp) {
    		return isContainAnnotationName(pjp, "NonAopLog");
    	}
    }
    
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    import static java.lang.annotation.ElementType.METHOD;
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    /**
     * @describe 不通过AOP打印日志,需要自己手动打印
     * @author YoungSmith
     * @date 2018年6月26日 下午3:03:57
     */
    @Target(value={METHOD, PARAMETER})
    @Retention(RUNTIME)
    @Documented
    public @interface NonAopLog {
    	String value() default "";
    }
    
    
    
    展开全文
  • 超大规模IT软件项目重构经验与实践 大东家 xiaohelong2005@126.com 1.为什么要重构? 一个项目需要重构,一般情况是因为这个项目可维护性差,或者其功能要扩展已无法适应当下的需要。一方比如,支持新的模型扩展...

    超大规模IT软件项目重构经验与实践

    大东家 xiaohelong2005@126.com

    1.为什么要重构?

    一个项目需要重构,一般情况是因为这个项目可维护性差,或者其功能要扩展已无法适应当下的需要。一方比如,支持新的模型扩展;另一方面,面对云化时代,无法从单机升级至并行抑或是分布式云计算支持。

    而我们碰到的就是这样一个程序,程序以VC6+MFC构建,代码规模在100多万行至200万行之间,单机程序,根据功能不同分为不同功能方向的子软件构成。站在这个工程所处的时代而言,客观来讲,程序架构设计合理,结构清晰,但这个当时的模式主流更多的是C++模式的应用,而无法站在应用或者模块化的角度进行组织;另一层面,由于程序在数据量大规模模拟时,出于对运行效率和规模的当下需求,原有架构模式必须模块化、并行化方能支持当下业务扩展;第三个层面,代码过于老旧,用的组件已然找不到资料,特别是数据等;第四个层面,代码的注释极少,只有一个固定的作者对其代码类做了解释,再一个就是基本上没有文档(注:在进行了较长一段时间后,拿了一些帮助手册等,对概念理解层面有一定帮助;最后一个层面,代码已经经历了较长时间的更改(包括界面翻译),中间也几经转手易人,这在概念的统一以及可以确定性的标准方面,对我们造成了一定的影响。

    2.重构准备工作

    面对一堆代码,从Java习惯转到C++习惯光从语言上切换,就需要克服内心恐惧。面前这一堆代码,就如处于浓雾中,思绪万千,不知从何下手,内心感觉到一阵恐惧。但是我有信心,有能力搞定他,正如以前经历过的几个大项目(与本项目不同)一样,凭借着自我的肯定与坚定的信心,这就开干了(注:在这个方面,过往吹过的牛都实现了,只是容易白头发)。

    另外,这是一个全新的领域,需要在较短时间内,补充专业名词、系统原理等概念进行全方位的学习理解,下了几本专业领域的书籍与相关论文,不得不说明的是,在这种压力下的学习真的很有效率。

    人力构成主要有开发团队,以及专家团队,虽然我们对工程实施很有经验也有自信,但相应的专业领域,这些特定行业内的顶级专家团队对我们最后的成功起到了决定性作用。当然,这个过程,也是需要磨合成本的。

    虽然成功是必然的,但不得不承认,成功也是有偶尔,这个偶尔就在于团队!(相对抽象,但仔细来讲,就是这一整个TEAM的整体输出能力,工作协调能力,通俗的讲,就如结婚,两口子搭的话,幸福一生;如果不搭,痛不欲生。)。所以,很庆幸,这样一个班子达到当前的效果,有如当前做订单可视化一般感同身受。

    有了信心,有了自我肯定,有了一个金牌TEAM,这就硬着头皮上了。自顶向下,梳理项目代码依纯关系、梳理类的继承关系,找到对象的相互引用(调用)的关系图,绘制出项目依赖包的关系、定位出被引用最多的函数和类,这一切磨难,在忐忑中前行。

    3.压力与机会,核心路线探索

    最初想将VC6的工程放到VS2019上编译,以方便调试,但出于对C++工程的熟悉程序,几经尝试均没有效果,只能保持现状,用VC6进行编译调试,用VS2019进行代码阅读与定位(这个问题,在后面团队对代码熟悉后,由C++经验多工程师重组了工程文件得以解决)。

    3.1. 第一次尝试

    这个时段,对相关概念已不再像最初那么陌生,出于项目本身是可以执行的,想通过直接将原有代码进行打包对外提供API的模式。通过一定时间的尝试,这种方式无法应对写API对内部状态的控制,也无法做到并行处理;当然,如果只是读,不需要改变状态,这种办法就是可行的,因此只能另谋他路。

    此时,时间已用到三个月,离任务目标时间仅剩7个月。

    ​​​​​​​3.2. 第二次尝试

    此时就得反思,该如何切入???

    还好,当我事有所思时,我一般在入睡前思考了几天(这也不好,激动处,易致失眠),终于确定了核心思路。即基于原有软件可以运行的模式,通过原有软件生成可以打通流程的文档,用这个文档驱动整个研发、测试以及结果校验流程,抓住核心要点,去掉复杂度,等核心流程打通,确定可行性以及可并行研发时,再通过加人和版本迭代方式快速大面积铺开。对,就这么干(失眠了,唉)。

    如何下手呢?嗯,团队相当给力,通过这个文档将代码业务梳理了一遍,对,就是湖南人的精神霸蛮一行一行打日志,打断点,终于相流程相关的业务代码、关键事件与活动梳理出来了。对,这就是业务驱动开发,只能这样,才能从迷雾中寻找到可以冲出来的路线。这一步走对了!!!

    这一下,此刻又面临一个决策问题,如何最快的方式移植代码。可以做的选择有:

    一、通过自己对业务的理解,重新做架构,只从原有代码中搬移核心融合算法;

    二、通过对原有系统类的梳理,通过压缩层级和模块化拆分最小程度改动代码,最大程度利用原有代码,同时兼顾了架构。

    考虑到第一种方式,最后即使移植成功,担心结果不被专家团认可,所以就倾向于第二种模式(第二种模式,中间也挫折,傻乎乎的尝试改变原有命名方式,后面回归到尽最大程度不改折腾了一个月)。时间一天一天过去,直到有一天和专家团进行了“和平友好的、激烈的、口干舌燥的意见交流”闭门会议,达成了采取第一种方式(这个我个人也是最初想选的,只是团队内部讨论担心结果不认同,所以没选择,即这么激烈、友好的又甲方爸爸认可这种结果,那不正合我意么)。

    此时,时间还剩下三个月(加上下一年的一个月,共四个月,这个时间点,团队成员的理想人选还在寻寻觅觅中,实话实说,大家心里慌得一P)

    ​​​​​​​3.3. 第三次尝试

    通过理想人员的加持,路线的多方认同,前面虽然走了弯路,但也看了更多的风景,有更多的经验,信心倍增,但时间却很紧。

    唯有牺牲多壮志,敢叫日月换新天。此刻的弟兄们,心中有梦想,眼中有亮光,对,干就完了,一天当两天用。

    虽然还有一堆TODO,但流程已然贯通,靴子落地,这一刻,兄弟们激动了。我猜专家团也跟我们一样,会很激动地拭一湿润的眼眶。

    4. 写在最后

    对于具备挑战的未知事件,如 果不能退缩的情况下,干就完了,管他。

    成功,更多的是一种偶然事件;但成功只要坚定信念,秉持着不服就干的精神又会成为一种必然事件。

    一个困难的事情,要搞定它需要有坚定的信心,吃苦耐劳的定图片,相互协调的团队以及资源的支持,这几个要素缺一不可。

    回到本次大规模C++代码工程上来说,核心思想是业务驱动的模式,通过极限编程,业务版本迭代,前期以流程贯通为目的进行。自顶向下业务理解,自下而上实施相结合的模式进行。

    展开全文
  • 项目重构的简单理解

    千次阅读 2020-02-15 10:18:04
    为啥需要重构呢? 之前一直以为系统重构就是那些系统架构师、大牛们玩的高端玩意儿 现在想想,有的项目是有很多代的,随着业务需求的迭代,问题也会越来越多。 如果业务繁杂,代码结构混乱,层次不清的话,会存在很...

    为啥需要重构呢?

    之前一直以为系统重构就是那些系统架构师、大牛们玩的高端玩意儿


    现在想想,有的项目是有很多代的,随着业务需求的迭代,问题也会越来越多。
    如果业务繁杂,代码结构混乱,层次不清的话,会存在很多冗余代码。

    就像我,一个安卓初学者,写个小项目都是使用分层式结构。如果功能点较少的话,这样的结构就够用了,每个层次都很清晰,用不着重构。但是,随着功能的增多,如果一个包里就有几十个文件,想想就很刺激。在这种情况下,拓展维护交接就变成了一个超级难的事情。

    之前接过一个某团队的项目去做,嗯,一言难尽,一个已经有年头的项目,随处可见的拼写错误,头重脚轻的函数,还有东拼西凑的代码,有些怀疑人生了。
    哈哈哈,有时候觉得别人的代码写的烂,其实自己也是烂代码的作者,没错了。
    在这里插入图片描述


    项目重构的理由我觉得应该是下面几个原因吧
    1、项目代码结构混乱,层次不清,代码风格不统一
    2、漏洞多,稳定性差
    3、有新的功能需求,但是之前的框架已经不能满足了
    4、各种大量接口回调导致内存泄漏严重
    5、业务代码和通用代码混合
    6、包含大量重复代码
    7、参数列表过长,参数太多的话,应该考虑用对象去替换参数列表

    其实,重构是一个不断发现问题、解决问题的过程。感觉重构就是悟性决定了成长。


    重构的目标

    1、改进软件设计。重构和设计的最重要的是设计吧,需要有一个解决方案,这个方案不能说是最正确的,但一定是最合理的,重构是让一些膨胀的代码和功能精简化
    2、使代码更容易理解,方便后期维护,也就是要让每个模块的定位清晰明确
    3、发现隐藏的代码缺陷
    4、代码风格要优雅~,内容质量高,按照合理的设计模式和编程思想去重构
    5、同步新的需求
    6、项目功能交互来个极致体验,功能上要要尽量做到不卡顿 不闪退,要满足产品需求的细节
    7、从长远来看,可以提高编程效率

    展开全文
  • 1.以往处理状态的一些方式第一种:App上挂globalData 这种方式就是直接写在App里面啦,取值赋值比较方便App.jsApp({globalData: {name: '前端学者',// ...other globalData},// ...other globalData});...
  • 聊聊前端项目重构

    2020-09-07 12:29:33
    为了提高项目的可维护性,于是决定了重构。两个月的时间,有限的知识储备,完成了第一次重构。 一、重构我都做了什么? 参考monorepo的思想,合并项目、拆分组件 JS迁移到TS 首页优化 css规范处理 添加单元测试 ...
  • Vue项目重构

    2020-06-10 17:14:07
    Vue项目重构Vue项目重构为什么要进行代码重构代码重构的方法尽可能的将项目代码组件化用vuex进行统一的状态管理重命名函数、组件用一些必要的配置文件合理使用异步组件尽量不将代码写死、尽量避免重复代码css尽可能...
  • 为什么重构:由于功能模块新增,交互体验优化,业务量增加,原有的项目架构会出现,维护困难,新增功能模块难度大,修改业务工作量大,bug问题排除困难。 什么时候重构:用数据举例来说吧,当应用用户>0时只需要...
  • 项目重构&性能优化

    2019-01-05 14:06:45
    重构的目标: 1.持续偏纠和改进软件设计  2.提升项目整体性能,优化代码结构 3.使代码更被其他人所理解  4.帮助发现隐藏的代码缺陷  5.从长远来看,有助于提高编程效率,增加项目进度     重构函数: ...
  • 一 选型前端:angularJS1.X,Angular Material后端:struts2,hibernate数据库:postgresql9.5二 问题1、选型上,作为一个以学生为主力军的团队,我认为选型上尽量选主流的框架。理由有2个:一是研究的人多,主要的...
  • 浅谈项目重构重要性

    千次阅读 2019-03-09 17:20:14
    无论我们微信、高德等应用都是伴随着用户数量增长,业务需求变化,整个项目从小到大,有浅到深一个演化递进的过程,项目从雏形交互应用到一个大型用户业务体验平台,从2-3个工程师到一个大型开发团队。由一开始几个...
  • 两年前的2016年,我还没有大学毕业,也才大三下学期,也还有自己的team,一起学习,一起成长,一起技术研究与试炼。不缅怀……当时和自己的team一起开发了“科技计划项目...
  • 项目重构之命令模式

    2019-03-18 02:33:56
    NULL 博文链接:https://ari.iteye.com/blog/691165
  • Android项目重构之路:架构篇

    千次阅读 2017-02-07 21:53:32
    原创文章,转载请注明:转载自Keegan小钢 ... 微信订阅号:keeganlee...Android项目重构之路:架构篇 Android项目重构之路:界面篇 Android项目重构之路:实现篇 去年10月底换到了新公司,做移动研发组的负责人,刚开
  • 描述 该项目的目的是重构由 David Lamber 开发的名为的现有软件。 外部链接
  • 重构微服务架构业务技术分析
  • Java项目重构总结

    千次阅读 2016-04-23 23:07:10
    重构步骤: 一、先建立可靠的测试环境:测试的目的是用于确保重构出来的代码能稳定运行,否则一旦对外发布就会容易出现问题。 总结:单元模块小重构,单元模块测试 二、分解并重组 1、什么情况下需要进行分解 ...
  • vtm-template 项目重构2.0
  • mscase 大师项目重构插件工具
  • ####即将发生重构代码,修复错误,感谢各位用户的支持Android自定义相册,实现了拍摄,图片选择(单选/多选),ImageLoader无绑定任由开发者选择 ### ImageSelector的优点 UI重改 所有功能可配置 解决OOM情况 图片...
  • springboot-refactor:针对重构项目例如SSM或SSH等架构的技术升级重构等总结了一个示例
  • 项目重构感悟

    2018-03-16 20:37:33
    重构是为了解决实际的项目问题,而不只是作为程序员的一个代码洁癖。所以,需要对新系统有可以量化的指标(eg. 性能提升5个点、开发工作量减少30% 等) 技术选型时,不要盲目最求新技术,需要尽量使用成熟、简单的方案...
  • ImageSelector, 项目重构中,地址:https

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 190,857
精华内容 76,342
关键字:

项目重构