代码重构!你敢吗?| 技术头条

640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | 大飞

本文经授权转大飞码字

今天讲述一个代码重构的经历。

2014年,我从基础架构部门,转调到业务部门。技术负责人想让我搞定业务系统的稳定性问题。

当时的业务系统确实存在不少问题,不过我初来乍到,对整体系统不熟悉,就想在熟悉一段时间后再动手。没想到,后面是事情自己找上了门。

那是一个周六的早上,我当时不在广州,而是去了深圳,去一个同学家。当时跟我同学聊的尽兴,就一直没看手机,间隔了一个多小时后,我打开微信一开,工作群里有几百个未读。看到我们技术负责人的头像一直在闪动,就意识到应该是出大问题了。

原来,是一个核心的业务系统出了一个bug, 影响到了一个重要的商户。

他们本意是给一个用户推送一条特定消息,消息里面还包含了一些隐私信息。不巧,一个新来的同学因为一个新的需求,修改了那部分的代码,引入了一个bug , 导致本来是发个一个特定用户的信息,发给了一堆人。

商户相当不满,后来是部门的公关出面,才将事情平息下来,经理那边也因为这个事情,拉我们到办公室批了一顿。

技术负责人也压力山大。我们几个人,在会议室里讨论了很久,最后大家都觉得如果要比较好的杜绝此类的问题,除了要加强各种测试等措施外,还有一个,就是要重构现有的代码。

因为这个系统是最核心的业务系统之一,而且几经易手,当时的代码已经变得极难维护,里面各种 if else 的分支,还有长达一千行一个的函数,注释不全,文档也不足,要想长期的维护下去,这个技术债是非偿还不可了。

大家面面相觑,虽然知道重构是最好的解决方案,但大家都不想搞呀。

后来,我考虑到,初来这里还是要做些事情才能得到大家认可的,就硬着头皮,把重构的这个任务给接了下来。

 

640?wx_fmt=png

确定重构的范围

 

接下这个任务后,我和项目组的成员就开始分析这个系统。

发现这个系统的业务流程很长,涉及到几十个子系统(微服务),还依赖几个外部门的服务。如果全部重构下来,估计一年都做不完,而且风险极大,重构一年的系统,然后再上线,谁敢呀,而且到那时,说不定黄花菜都凉了。

觉得这样肯定不行。

我们就重新梳理了一遍,把整个系统划分成了三个部分,我们发现中间部分的修改最频繁,出问题的频率也最大,就决定先重构中间流程部分的代码。

项目规划部分,我们对项目进行了分期,中间部分的重构作为第一期,其他两部分可以作为二期,三期项目来做。一个是可以极大地减少压力,使得的事情更加容易把握,另一个是间隔一段时间有产出也能给团队带来信心。

 

640?wx_fmt=png

设计好验证的方式

 

当确认好重构的范围后,接下来的事情,就是要考虑如何来验证重构后的代码了。

这个是重构代码最重要的一个部分,如果没办法验证重构代码的正确性,你是不敢上线的,就算硬上了,也会睡不好觉。

一般重构代码的验证,可以采用测试代码,测试用例覆盖的方法。(这部分可以参考 《重构》)。但我们发现,我们要重构的这个部分,不能采用这种方式来验证。

因为业务逻辑很复杂,而且涉及到太多的外围系统,一个是测试用例很难覆盖全面,另外一个是没有办法可以很好的隔离外部系统的依赖。

我们分析了整个系统,发现这个系统的功能是,接受商户过来一个请求,然后进行各种权限,角色等的判断,再根据各个参数去各个依赖系统拉取数据,最后组装出一个新的包,再把这个新的包发送到隔壁部门的下游系统。

后来,我们想了双流程验证的方案。

我们将重构部分的代码,全部封装起来,然后提供一个新的接口,一个请求进来后,我们分别执行旧的业务逻辑,也将请求发给新接口。在流程的最后,我们将新旧流程构造出的字段,进行逐个字段的对比。新流程只验证正确性,不做实际的输出。

为了保证验证的效果,验证要在线上进行,所以还要再结合后面的灰度流程。

 

640?wx_fmt=png

尽一切努力,搞清重构代码的逻辑

 

当我们确定好验证方式后,接下来就是正式的工作了,重构代码。重写代码本身是不难的,但遇到的麻烦是,几乎没有文档,注释也很少,通过看代码只是搞懂了百分之五十左右的逻辑,还有一大部分的逻辑,无法理清楚。

后来,我们想到一个办法,把代码版本管理系统的log 全部拉出来。通过log我们找到了各部分逻辑不清晰的代码的负责人,然后一个一个的去跟他们聊,跟他们请教。运气好的是,大部分的人员都还在,中间还跟产品经理聊了不少,终于,把整个的逻辑搞懂了百分之九十几。

因为有了上面的双流程验证和下面灰度逻辑,我们觉得,可以开始上线验证了。

 

640?wx_fmt=png

灰度,一定要灰度

 

接下来,就要开始我们的灰度验证流程了。因为故障的影响很大,所以我们灰度的特别小心。

我们内部有灰度系统,但内部系统的灰度粒度比较大,为了保险我们需要更小粒度的灰度,所以我们自己写了灰度的逻辑代码,直接嵌入到了系统里面。

一开始的时候,极度小心,几乎是一个商户,一个商户灰度的。灰度完后,我们每间隔一段时间,就分析一遍log和监控,看看有没有隐藏的问题。

最终,我们确实在这个灰度的过程中,发现了不少的问题,不过因为涉及的用户很少,都没有造成大的影响。

这种极小范围的灰度,大概持续了一周左右的时间,后面慢慢加快了灰度的速度。大概花了一个月的时间,覆盖了全部的用户。

中间过程,几乎没有出现什么大的问题,可以说是比较成功的一次重构。

 

640?wx_fmt=png

控制好各方预期

 

最后一个点,跟技术无关,是关于相关人员的预期,包括上级的预期,同级的预期,下属的预期。

我当时知道这个项目有难度,自己心里也没底,所以跟上级说去试一试,后来谈成可以在过程接受两次中等故障。当然最后结果比预期好,没有一次中等故障,只有过两次小故障。

同级这块,也是跟大家说,尽力去试试,不过确实不是很有把握,也算是降低了他们的预期。

对于下面的兄弟,我是跟大家说,这是一件可以稳固我们团队地位的事情,拼死也要拿下这一仗。后面大家都很齐心,一起完成了这个在当时看来挺难的一个任务。

这个策略,是我第一年工作的时候,我导师告诉我的,内紧外松。这样外面对你的预期是比较低,内部却很拼命的做,最后的结果,往往比较容易超出大家的预期。

我觉得这是一个很好的策略。

 

640?wx_fmt=png

结语

 

最后,我们顺利完成了这次的重构任务,也做出了我们在新团队的影响力。后面再来回顾,发现我们做对了不少的事情。没有一上来就开干,因为信心不足,反而是小心翼翼,也因为信心不太足,在不断的降低外界的预期,最后一步一步,紧遵流程,获得了不错的结果。

作者:大飞。十年互联网人,资深架构师,技术leader。

声明:版权归作者所有,如需转载请联系原作者。

国家认证的Python工程师有哪些能力要求?

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

【End】

640?wx_fmt=jpeg

 热 文 推 荐 

☞下过富士康工厂、做过华为外包,这位程序员是如何花 6 年逆袭成为技术大佬的?

苹果高通 5G 开战!

我是技术男,也曾创业过,也拿过风投......

身为程序员的父母,你年薪多少才能让“码二代” 不输在起跑线上

搜狗员工吐槽“统计加班时长裁人”,CEO 王小川破口大骂:“赶快滚”

漫话:如何给女朋友解释什么是系统可用性? | 技术头条

EOS现状: 72%应用涉赌被列为高危, 说好的诗和远方, 你竟沦落成了这样?

ICPC 2019国际大学生程序设计竞赛,中国高校未能夺冠

☞刺激!我31岁敲代码10年,明天退休!


 

System.out.println("点个在看吧!");
console.log("点个在看吧!");
print("点个在看吧!");
printf("点个在看吧!\n");
cout << "点个在看吧!" << endl;
Console.WriteLine("点个在看吧!");
Response.Write("点个在看吧!");
alert("点个在看吧!")
echo "点个在看吧!"

640?wx_fmt=gif点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

640?wx_fmt=png你点的每个“在看”,我都认真当成了喜欢640?wx_fmt=png

展开阅读全文

你敢吗?抛砖引玉的问题,值得一看

07-13

路过的技术牛人,想请教一个问题。我想用fork产生3个子进程,分别执行不同的任务。并且给他们设定不同的优先级,让他们按照优先级执行。rn我的代码在下面。进程1,child1的优先级是14.child2的优先级是10.child3的优先级是-3.按道理应该是子进程child3先执行。rnrn#includern#includern#includern#includern#includern#includernrnrnvoid main()rnrn pid_t father,child1,child2,child3;rn int prio;rn father=getpid();rn setpriority(PRIO_PROCESS,0,20);rn //nice(10);rn printf("the father ID is : %d\n",father);rn prio=getpriority(PRIO_PROCESS,0);rn printf("the father priority is %d\n",prio);rn child1=fork();rn if(child1==0) rn setpriority(PRIO_PROCESS,0,14);rn prio=getpriority(PRIO_PROCESS,0);rn printf("the child one ID is : %d\n",getpid());rn printf("the child one priority is %d\n",prio);rn rn else if(child1>0)rn child2=fork();rn if(child2==0) rn setpriority(PRIO_PROCESS,0,10);rn prio=getpriority(PRIO_PROCESS,0);rn printf("the child two ID is : %d\n",getpid());rn printf("the child two priority is %d\n",prio);rn rn else if(child2>0)rn child3=fork();rn if(child3==0) rn setpriority(PRIO_PROCESS,0,-3);rn prio=getpriority(PRIO_PROCESS,0);rn printf("the child three ID is : %d\n",getpid());rn printf("the child three priority is %d\n",prio);rn rn else if(child3>0) rn printf("my ID is %d\n",getpid());rn printf("my prio is %d\n",getpriority(PRIO_PROCESS,0));rn rn rn rn rnrnrnrn执行结果是:rn先执行1,再 2,再3rn 论坛

170道Java工程师面试题,你敢挑战吗?

03-24

1、面向对象的特征有哪些方面?rn2、访问修饰符public,private,protected,以及不写(默认)时的区别?rn3、String 是最基本的数据类型吗?rn4、float f=3.4;是否正确?rn5、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?rn6、Java有没有goto?rn7、int和Integer有什么区别?rn8、&和&&的区别?rn9、解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。rn10、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?rn11、switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?rn12、用最有效率的方法计算2乘以8?rn13、数组有没有length()方法?String有没有length()方法?rn14、在Java中,如何跳出当前的多重嵌套循环?rn15、构造器(constructor)是否可被重写(override)?rn16、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?rn17、是否可以继承String类?rn18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?rn19、String和StringBuilder、StringBuffer的区别?rn20、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?rn21、描述一下JVM加载class文件的原理机制?rn22、char 型变量中能不能存贮一个中文汉字,为什么?rn23、抽象类(abstract class)和接口(interface)有什么异同?rn24、静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?rn25、Java 中会存在内存泄漏吗,请简单描述。rn26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?rn27、阐述静态变量和实例变量的区别。rn28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?rn29、如何实现对象克隆?rn31、String s = new String("xyz");创建了几个字符串对象?rn32、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?rn33、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?rn34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?rn35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?rn36、Java 中的final关键字有哪些用法?rn38、数据类型之间的转换:rn39、如何实现字符串的反转及替换?rn40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?rn41、日期和时间:rn42、打印昨天的当前时刻。rn43、比较一下Java和JavaSciprt。rn44、什么时候用断言(assert)?rn45、Error和Exception有什么区别?rn46、try里有一个return语句,那么紧跟在这个try后的finally里的代码会不会被执行,什么时候被执行,在return前还是后?rn47、Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?rn48、运行时异常与受检异常有何异同?rn49、列出一些你常见的运行时异常?rn50、阐述final、finally、finalize的区别。rn51、类ExampleA继承Exception,类ExampleB继承ExampleA。rn请问执行此段代码的输出是什么?rn52、List、Set、Map是否继承自Collection接口?rn53、阐述ArrayList、Vector、LinkedList的存储性能和特性。rn54、Collection和Collections的区别?rn55、List、Map、Set三个接口存取元素时,各有什么特点?rn56、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?rn57、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?rn58、线程的sleep()方法和yield()方法有什么区别?rn59、当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?rn60、请说出与线程同步以及线程调度相关的方法。rn61、编写多线程程序有几种实现方式?rn62、synchronized关键字的用法?rn63、举例说明同步和异步。rn64、启动一个线程是调用run()还是start()方法?rn65、什么是线程池(thread pool)?rn66、线程的基本状态以及状态之间的关系?rn67、简述synchronized 和java.util.concurrent.locks.Lock的异同?rn68、Java中如何实现序列化,有什么意义?rn69、Java中有几种类型的流?rn70、写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数。rn71、如何用Java代码列出一个目录下所有的文件?rn72、用Java的套接字编程实现一个多线程的回显(echo)服务器。rn73、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?rn74、你在项目中哪些地方用到了XML?rn75、阐述JDBC操作数据库的步骤。rn76、Statement和PreparedStatement有什么区别?哪个性能更好?rn77、使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?rn78、在进行数据库编程时,连接池有什么作用?rn79、什么是DAO模式?rn80、事务的ACID是指什么?rn81、JDBC中如何进行事务处理?rn82、JDBC能否处理Blob和Clob?rn83、简述正则表达式及其用途。rn84、Java中是如何支持正则表达式操作的?rn85、获得一个类的类对象有哪些方式?rn86、如何通过反射创建对象?rn87、如何通过反射获取和设置对象私有字段的值?rn88、如何通过反射调用对象的方法?rn89、简述一下面向对象的"六原则一法则"。rn90、简述一下你了解的设计模式。rn91、用Java写一个单例类。rn92、什么是UML?rn93、UML中有哪些常用的图?rn94、用Java写一个冒泡排序。rn95、用Java写一个折半查找。rn96、阐述Servlet和CGI的区别?rn97、Servlet接口中有哪些方法?rn98、转发(forward)和重定向(redirect)的区别?rn99、JSP有哪些内置对象?作用分别是什么?rn100、get和post请求的区别?rn101、常用的Web服务器有哪些?rn102、JSP和Servlet是什么关系?rn103、讲解JSP中的四种作用域。rn104、如何实现JSP或Servlet的单线程模式?rn105、实现会话跟踪的技术有哪些?rn106、过滤器有哪些作用和用法?rn107、监听器有哪些作用和用法?rn108、web.xml文件中可以配置哪些内容?rn109、你的项目中使用过哪些JSTL标签?rn110、使用标签库有什么好处?如何自定义JSP标签?rn111、说一下表达式语言(EL)的隐式对象及其作用。rn112、表达式语言(EL)支持哪些运算符?rn113、Java Web开发的Model 1和Model 2分别指的是什么?rn114、Servlet 3中的异步处理指的是什么?rn115、如何在基于Java的Web项目中实现文件上传和下载?rn116、服务器收到用户提交的表单数据,到底是调用Servlet的doGet()还是doPost()方法?rn117、JSP中的静态包含和动态包含有什么区别?rn118、Servlet中如何获取用户提交的查询参数或表单数据?rn119、Servlet中如何获取用户配置的初始化参数以及服务器上下文参数?rn120、如何设置请求的编码以及响应内容的类型?rn121、解释一下网络应用的模式及其特点。rn122、什么是Web Service(Web服务)?rn123、概念解释:SOAP、WSDL、UDDI。rn124、Java规范中和Web Service相关的规范有哪些?rn125、介绍一下你了解的Java领域的Web Service框架。rn126、什么是ORM?rn127、持久层设计要考虑的问题有哪些?你用过的持久层框架有哪些?rn128、Hibernate中SessionFactory是线程安全的吗?Session是线程安全的吗(两个线程能够共享同一个Session吗)?rn129、Hibernate中Session的load和get方法的区别是什么?rn130、Session的save()、update()、merge()、lock()、saveOrUpdate()和persist()方法分别是做什么的?有什么区别?rn131、阐述Session加载实体对象的过程。rn132、Query接口的list方法和iterate方法有什么区别?rn133、Hibernate如何实现分页查询?rn134、锁机制有什么用?简述Hibernate的悲观锁和乐观锁机制。rn135、阐述实体对象的三种状态以及转换关系。rn136、如何理解Hibernate的延迟加载机制?在实际应用中,延迟加载与Session关闭的矛盾是如何处理的?rn137、举一个多对多关联的例子,并说明如何实现多对多关联映射。rn138、谈一下你对继承映射的理解。rn139、简述Hibernate常见优化策略。rn140、谈一谈Hibernate的一级缓存、二级缓存和查询缓存。rn141、Hibernate中DetachedCriteria类是做什么的?rn142、@OneToMany注解的mappedBy属性有什么作用?rn143、MyBatis中使用#和$书写占位符有什么区别?rn144、解释一下MyBatis中命名空间(namespace)的作用。rn145、MyBatis中的动态SQL是什么意思?rn146、什么是IoC和DI?DI是如何实现的?rn147、Spring中Bean的作用域有哪些?rn148、解释一下什么叫AOP(面向切面编程)?rn149、你是如何理解"横切关注"这个概念的?rn150、你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念?rn151、Spring中自动装配的方式有哪些?rn152、Spring中如何使用注解来配置Bean?有哪些相关的注解?rn153、Spring支持的事务管理类型有哪些?你在项目中使用哪种方式?rn154、如何在Web项目中配置Spring的IoC容器?rn155、如何在Web项目中配置Spring MVC?rn156、Spring MVC的工作原理是怎样的?rn157、如何在Spring IoC容器中配置数据源?rn158、如何配置配置事务增强?rn159、选择使用Spring框架的原因(Spring框架为企业级开发带来的好处有哪些)?rn160、Spring IoC容器配置Bean的方式?rn161、阐述Spring框架中Bean的生命周期?rn162、依赖注入时如何注入集合属性?rn163、Spring中的自动装配有哪些限制?rn164、在Web项目中如何获得Spring的IoC容器?rn165. 大型网站在架构上应当考虑哪些问题?rn166、你用过的网站前端优化的技术有哪些?rn167、你使用过的应用服务器优化技术有哪些?rnrnrn你能答对几道呢?也可以加我好友一起讨论。rn 论坛

那么问题来了,你敢点开这吗?

02-04

嘻嘻,小编编再次出场了,隆重欢迎一下吧!rnrn春节马上要到来了,你准备怎么过呢?是通宵和朋友去KTV、打牌、聊天、旅游,还是……[img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/13.gif][/img]rnrn打发时间的方式有很多种,不知道你会选择哪一种呢?[img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/32.gif][/img]rnrn为了丰富你的假期生活,小编编给你提供了另外一种假期选择——移动开发精品课程学习,你不用再担心假期无聊喽![img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/42.gif][/img]rnrn[url=http://edu.csdn.net/course/detail/394][b]SpriteKit游戏引擎视频教程[/b][/url]rnrn[url=http://edu.csdn.net/course/detail/394][img=https://img-bbs.csdn.net/upload/201502/04/1423032577_822260.png][/img][/url]rn[color=#FF0000][b]课程讲师:[/b][/color]李宁rnrn[color=#FF0000][b]课程简介:[/b][/color]SpriteKit是Apple新推出的2D游戏引擎,与Cocos2d-x类似。可以使用Objective-C和Swift语言开发。可开发iOS和Mac OS X下的2D游戏。本课程主要介绍了SpriteKit的常用技术,包括基础知识、action、粒子系统、物理引擎等。rnrn[color=#FF0000][b]价格:[/b][/color]2400C币[color=#FF0000](¥120元)[/color]rnrn[url=http://edu.csdn.net/course/detail/330][b]从零开始掌握iOS8开发技术(Swift版)第1季:iOS基础知识[/b][/url]rnrn[url=http://edu.csdn.net/course/detail/330][img=https://img-bbs.csdn.net/upload/201502/04/1423033449_638174.png][/img][/url]rn[color=#FF0000][b]课程讲师:[/b][/color]李宁rnrn[color=#FF0000][b]课程简介:[/b][/color]本课程主要介绍了开发iOS app的一些基本情况。例如,需要的硬件和软件条件,如何申请开发者账号,XCode的常用功能介绍。最后给出一个iOS App的案例来演示开发App的过程。rnrn[color=#FF0000][b]价格:[/b][/color]400C币(¥20元)rnrn[b]欲了解更多精品课程内容,请点击这里:[/b][url=http://edu.csdn.net]http://edu.csdn.net[/url] 论坛

代码重构

11-08

[code=VB.NET]Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tickrn Timer2.Enabled = Truernrn Timer2.Interval = 1000rn '每一秒刷新一次rn '遍历取值问题解决,i=i+1去掉rn Tryrnrn rnrn Dim str2 As String = "server=localhost;database=test;user id=root;password=123;pooling=false;"rnrn Dim conn1 As MySqlConnection = New MySqlConnection(str2)rn conn1.Open()rnrn '查詢資料rn Dim str1 As String = "select * from wait_message where ustatus = '-1'"rn Dim adapter1 As Common.DbDataAdapter = New MySqlDataAdapter(str1, conn1)rnrn '將查詢結果放到記憶體testDataSet上的"wait_message"表格內rn Dim testDataSet As DataSet = New DataSetrn adapter1.Fill(testDataSet, "wait_message")rnrn Dim i As Integer = 0rnrn '它是按照0,2,4循环的.如果把i=i+1去掉可以读取到全部,不过跟弹出框和刷新不同步,控件读取数据的时间跟发送时间不同步问题,现在的问题还是不太清楚发送的数据有没有问题rnrn For i = 0 To testDataSet.Tables("wait_message").Rows.Count - 1rnrnrn MobPort.Text = testDataSet.Tables("wait_message").Rows(i).Item("uportnum")rn TelNum_Text.Text = testDataSet.Tables("wait_message").Rows(i).Item("uphonenum")rn 'DeleteSms_Index.Text = testDataSet.Tables("wait_message").Rows(i).Item("ucontent") '此行是主鍵值,所以不打算顯示rn SendSms_Text.Text = testDataSet.Tables("wait_message").Rows(i).Item("ucontent")rn ReceiveSms_Text.Text = testDataSet.Tables("wait_message").Rows(i).Item("uIndex")rn DeleteSms_Index.Text = testDataSet.Tables("wait_message").Rows(i).Item("ustatus")rn 'MsgBox(testDataSet.Tables("wait_message").Rows.Count - 1)rn 'MsgBox(MobPort.Text & testDataSet.Tables("wait_message").Rows(i).Item("uportnum"))rn ' MsgBox(i)rn Nextrnrnrn Catch ex As Exceptionrn MsgBox(ex.Message)rn End Tryrnrnrnrnrn System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Defaultrn If Len(Trim(TelNum_Text.Text)) >= 11 And Sms_Send(Trim(TelNum_Text.Text), Trim(SendSms_Text.Text)) Thenrn Sms_Disconnection_Button.Enabled = Falsern MsgBox("发送短信成功!", MsgBoxStyle.Information, "提示")rn 'Elsern ' MsgBox("发送短信失败!", MsgBoxStyle.Critical, "警告")rn System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Defaultrnrn Dim str2 As String = "server=localhost;database=test;user id=root;password=123;pooling=false;"rnrn Dim conn1 As MySqlConnection = New MySqlConnection(str2)rnrn conn1.Open()rnrn Dim comstr As Stringrn comstr = " UPDATE wait_message SET ustatus = '1' WHERE ustatus = '-1' "rn Dim adapter1 As Common.DbDataAdapter = New MySqlDataAdapter(comstr, conn1)rn Dim testDataSet As DataSet = New DataSetrn adapter1.Fill(testDataSet, "wait_message")rnrnrnrnrnrn ''關閉資料庫的連結rn conn1.Close()rn 'conn1.ConnectionString = Nothingrnrnrnrn End Ifrnrnrnrnrnrnrn Timer2.Enabled = Falsernrnrnrnrn End Sub[/code]rn================rn怎么把这两个dataSet和发送消息的代码分别重构为几个函数~ 论坛

代码重构~

06-01

package com.eetrust.cpm.IPparse;rnrnrnrnrnrnpublic class Directory2 rnrn rn rn//private static File[] strPath2;rnrnrnrnrnpublic static String convertingStr(String lineStr) rn String retVal = ""; rn return retVal; rn rnrnrnrn rnpublic static void recursion(String root, Vector vecFile) rn File file = new File(root); rn File[] subFile = file.listFiles(); rn rn rn if (subFile.length == 0) rn System.out.println(file.getAbsolutePath() + " is null");rn elsern rn for (int i = 0; i < subFile.length; i++) rn if (subFile[i].isDirectory()) rn rn rn rn rn recursion(subFile[i].getAbsolutePath(), vecFile);rn rn rn else rn rn String filename = subFile[i].getName();rn rn vecFile.add(subFile[i].getAbsolutePath()); rn rn rn rn rnrnrn rn rnrnpublic String GetNowDate()rn String temp_str="";rn Date dt = new Date();rn //最后的aa表示“上午”或“下午” HH表示24小时制 如果换成hh表示12小时制rn SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss aa");rn temp_str=sdf.format(dt);rn return temp_str;rn rnrnrnrn/** rn * @param args rn * @throws IOException rn */ rnpublic static void main(String[] args) throws IOException rn rnrn rnrn rn Map map = new HashMap(); rnrn IPtest ipTest = new IPtest();rn String path = ipTest.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();rn rn //System.out.println(path);rn// if (path.indexOf("WEB-INF") > 0) rn// path = path.substring(1, path.indexOf("/WEB-INF/"));rn// rn path+="/qqwry";rn // 指定纯真数据库的文件名,所在文件夹rn IPSeeker ip = new IPSeeker("QQWry.Dat", path);rn // 测试IP 58.20.43.13rn System.out.println(path);rn rn rn rn Vector vecFile = new Vector(); rn recursion("/opt/haproxy_temp_log", vecFile); rnrn for (String fileName : vecFile) rn System.out.println(fileName); rn Pattern pattern = Pattern.compile("\\S*\\d+\\.\\d+\\.\\d+\\.\\d+$"); rn Matcher m2 = pattern.matcher(fileName);rn if(m2.matches()!=false)rnrn System.out.println("不需要处理!@");rn rn else if(fileName.indexOf("cache.rightgo.net")!=-1)rn rn System.out.println("不需要分析!");rn else rn rn rn rn rn BufferedReader br = new BufferedReader(new FileReader(fileName)); rn rn //System.out.println(i);rn rn String line = null;rnrn while ((line = br.readLine()) != null)rn rn Pattern p = Pattern.compile(":\\s([^:]*):");//这个匹配还是有点取巧了。rn //可以这样":\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s*:"安全一点rnrn Matcher m = null;rnrn if(!"".equals(line))rn m = p.matcher(line);rn while(m.find())rn rn String key1 = ip.getIPLocation(m.group(1).trim()).getCountry();rn rn rn rn //北京市、上海市、天津市、重庆市。rn rn // System.out.println(key);rnrn if(key1.indexOf("黑龙江")!=-1)rn key1=key1.substring(0, 3);rn else if(key1.indexOf("省")!=-1^key1.indexOf("市")!=-1)rn rn rn key1=key1.substring(0, 2);rn rn rn rn rn else if(key1.indexOf("香港")!=-1)rn key1=key1.substring(0, 2);rn else if(key1.indexOf("澳门")!=-1)rn key1=key1.substring(0, 2);rn rn rn rn elsern key1="其它";rn rn rn rn rn rn rn rn String key2 = ip.getIPLocation(m.group(1).trim()).getArea();rn rn rn if(key2.indexOf("电信")!=-1)rn rn rn key2="电信";rn rn else if(key2.indexOf("移动")!=-1)rn key2="移动";rn rn else if(key2.indexOf("网通")!=-1^key2.indexOf("联通")!=-1)rn key2="联通";rn rn else if(key2.indexOf("学")!=-1^key2.indexOf("教")!=-1)rn key2="教育网";rn elsern key2="其它";rn rn rn rnrnrn String fileName2;rnrn rn rn if(fileName.indexOf(":80")!=-1)rnrn rn fileName2 = fileName.substring(fileName.lastIndexOf(File.separator)+1,fileName.lastIndexOf(":80"));rn rn elsernrn rn fileName2 = fileName.substring(fileName.lastIndexOf(File.separator)+1,fileName.length());rnrnrn rnrn //System.out.println(fileName2);rn rnrn String key = key1+key2+fileName2;rn rnrn rn //String key = key1+key2+fileName;rnrn rn // System.out.println(key);rn rn // System.out.println(files[i].getName());rn rn rn rn if (map.containsKey(key)) rn Integer temp2 = map.get(key);rn map.put(key, ++temp2);rn else rn map.put(key, new Integer(1));rn rn rnrn rn rn rn // end of while;rn rn rn rn // end of if;rn rn rnrn //end of while;rn rnrnrnrn br.close(); rn rnrn rn rn rn rnrntry rn Class.forName("com.mysql.jdbc.Driver");rn //定义所要用到的三个数据库应用对象rn // Connection con=null; //连接对象rn // Statement sql=null; //Statement对象(SQL语句)rn// ResultSet rs=null; //结果集对象rn //进行数据源的连接rn rn Connection con;rntryrn con = DriverManager.getConnection ("jdbc:mysql://localhost/cdn_web_user_stats?user=root&password=rjkj@rjkj&useUnicode=true&characterEncoding=utf8");rnrn List> list2 = new LinkedList>();rn list2.addAll(map.entrySet());rn for(Iterator> ite = list2.iterator(); ite.hasNext();) rn rn Map.Entry map2 = ite.next();rn rn rn System.out.println(map2.getKey());rn rn rn String n;rn rnrn if(map2.getKey().indexOf("黑")!=-1 )rn rn System.out.println(map2.getKey());rn n=map2.getKey().substring(5,map2.getKey().length());rn rn rn rn rn if(map2.getKey().indexOf("教")!=-1)rn n=map2.getKey().substring(6,map2.getKey().length());rn rn rn else if(map2.getKey().indexOf("教")!=-1)rn n=map2.getKey().substring(5,map2.getKey().length());rn rn rn elsern n = map2.getKey().substring(4,map2.getKey().length());rn rn rnrn rnrnrnrn System.out.println(n);rn rn rn rn rn rnrn Statement stmt = con.createStatement();rn rn rn rn rn rn String sql2 = "CREATE TABLE IF NOT EXISTS `cdn_web_user_stats`.`"+n+"` ("rn +" `id` int(11) NOT NULL AUTO_INCREMENT,"rn +" `date` date NOT NULL," rn +"`zone` char(50) NOT NULL," rn +"`nettype` varchar(50) NOT NULL," rn +"`cnt` int(32) unsigned NOT NULL,"rn +"PRIMARY KEY (`id`)," rn +" UNIQUE KEY datezone (`date`,`zone`,`nettype`),"rn +"KEY `cnt` (`cnt`)" rn +" ) ENGINE=MyISAM DEFAULT CHARSET=utf8";rn stmt.execute(sql2);rn rn rn rn String zone1;rn rn if(map2.getKey().indexOf("黑")!=-1)rn rn rn zone1 = map2.getKey().substring(0, 3);rn rn elsern rn zone1 = map2.getKey().substring(0, 2);rn rn rn rn rn String net;rn rn if(map2.getKey().indexOf("黑")!=-1)rn rn net = map2.getKey().substring(3, 5);rn rn rn if(map2.getKey().indexOf("教")!=-1)rn net = map2.getKey().substring(3, 6);rn rn rn else if(map2.getKey().indexOf("学")!=-1 ^ map2.getKey().indexOf("教")!=-1)rn net = map2.getKey().substring(2, 5);rn rn elsern rn net = map2.getKey().substring(2, 4);rn rn rn rn int value = map2.getValue();rn rn rn rn rn String sql="insert into `cdn_web_user_stats`.`"+n+"`(date,zone,nettype,cnt) values(?,?,?,?)";rn rn rn rn System.out.println(sql);rn PreparedStatement pstmt = con.prepareStatement(sql);rn rn rn rn Calendar calendar = Calendar.getInstance();rn calendar.add(Calendar.DATE, -1); //得到前一天rn Date date = calendar.getTime();rn DateFormat df = new SimpleDateFormat("yyyy-MM-dd");rn rn String n1=df.format(date);rn rn rn pstmt.setString(1, n1);rn pstmt.setString(2,zone1);rn pstmt.setString(3, net);rn pstmt.setInt(4, value);rn rn if(pstmt.executeUpdate()>0) //判断结果集是否为空,如果不为空则表示有记录rn rn System.out.println("添加成功!");rn rn else rn System.out.println("添加失败!");rn rn //end of forrn // //end of foern rn catch (SQLException e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rnrn rn rn catch (ClassNotFoundException e) rn // TODO Auto-generated catch blockrn e.printStackTrace();rn rn rn rn rn rnrnrnrnrnrn// end of mainrnrnrn 论坛

没有更多推荐了,返回首页