ALL is Well!

敏捷是一条很长的路,摸索着前进着

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  30 随笔 :: 23 文章 :: 71 评论 :: 0 Trackbacks

近日有人问起,“你认为如何能提高代码的质量”,虽然都说出来了,但缺乏条理,特总结于此。

首先,应明确什么样的代码算是质量高的。然后才能知道如何去做。

我觉得,高质量的代码应该至少包括:

1.可读性。

2.可维护性。

代码的可读性同样有助于代码的可维护性。有时候在一个项目里,你修改的代码未必是自己写的,如果代码写的可读性很差,那将是非常痛苦的。

一、可读性

1.包名、类名、成员变量名、方法名、局部变量名等的命名应仔细斟酌。尽量做到读一段代码,就像是读一句话一样,在阅读的过程中就能理解其中的逻辑。

2.包下面应包含哪些类,这也是有讲究的。不能太随意。从包中应该可以大概看出类的功能或所在层次。

3.一个方法只要实现一个功能。这一点很重要,首先利于阅读,方法的名字可以告诉你它的功能。

4.方法的实现不宜过长,个人写代码的习惯是,一个方法的长度不会超过电脑的一屏。也就是不用拖动滚动条便可把实现尽收眼底。

二、可维护性

1.代码写的要灵活,尤其是一些配置文件。比如写一个下载程序,文件的放置路径就不能在代码中写死。因为一来以后要变动的话,还要来改程序,并重新部署;二来开发的环境与正式的环境有所不同,写死也不利于部署。

最典型的例子就是数据库的连接信息,url、用户名、密码等,开发环境与正式环境一般不会相同,把这些信息写在配置文件里为好。

2.提高的代码复用,以提高代码的维护性。

举个反例吧。我们的系统中有很多生成Excel文件并在浏览器端下载的功能要求,由于这些功能由不同的人来完成,结果类似的程序写了二十几份,都是互相拷贝而来。

当时我们用的是POI的低版本,后来进行了POI的升级,有一些API不能使用了,于是改了二十几个类。如果把这些功能复用一些,也许只要修改一个类文件就搞定了。

3.多用一些设计模式,提高代码的层次感。使得修改代码的时候,影响范围达到尽量的小。这个就有难度了。平时要慢慢积累才行。

常用的模式 工厂模式、模板模式、适配器模式、策略模式、代理模式(动态代理) 等。这些模式在平时的工作中经常用到,应该熟练运用才行。

下面是一些代码片段:

 1private void checkJob(JobConfig job) {   
 2    JobConfig original = find(job);   
 3    if (original != null// 已存在的任务 进行替换   
 4        if (original.equals(job)) // 任务没有变更   
 5        }
 else if (replace(original, job)) // 替换作业成功 则加入到新作业列表中   
 6            allJobs.remove(original);   
 7        }
   
 8    }
 else if (schedule(job)) // 新添加的任务   
 9        log.info(Log4jHelper.getLogMain(job) + "派发成功。");   
10    }
   
11}
   
12  
13private JobConfig find(JobConfig job) {   
14    for (JobConfig j : allJobs) {   
15        // 找到相同作业ID的任务   
16        if (j.getJobId().equals(job.getJobId())) {   
17            return j;   
18        }
   
19    }
   
20    return null;   
21}
   
22  
23private boolean replace(JobConfig original, JobConfig job) {   
24    return remove(original) && schedule(job);   
25}
   
26  
27private boolean remove(JobConfig job) {   
28    try {   
29        return schedulerService.remove(job);   
30    }
   
31    catch (SchedulerException e) {   
32        e.printStackTrace();   
33        log.error(Log4jHelper.getLogMain(job) + "移除失败。");   
34    }
   
35    return false;   
36}
   
37  
38private boolean schedule(JobConfig job) {   
39    try {   
40        schedulerService.schedule(job);   
41    }
   
42    catch (Exception e) {   
43        e.printStackTrace();   
44        log.error(Log4jHelper.getLogMain(job) + "派发失败。");   
45        return false;   
46    }
   
47    return true;   
48}

49

  1import java.io.IOException;   
  2import java.io.InputStream;   
  3import java.lang.reflect.Constructor;   
  4import java.lang.reflect.Field;   
  5import java.lang.reflect.InvocationTargetException;   
  6import java.lang.reflect.Method;   
  7import java.lang.reflect.ParameterizedType;   
  8import java.net.MalformedURLException;   
  9import java.net.URL;   
 10import java.util.ArrayList;   
 11import java.util.List;   
 12  
 13import org.apache.commons.collections.Predicate;   
 14import org.springframework.core.io.ClassPathResource;   
 15import org.springframework.core.io.Resource;   
 16import org.springframework.core.io.support.PathMatchingResourcePatternResolver;   
 17import org.springframework.core.type.classreading.CachingMetadataReaderFactory;   
 18import org.springframework.core.type.classreading.MetadataReader;   
 19import org.springframework.core.type.classreading.MetadataReaderFactory;   
 20  
 21import com.lim.base.exception.AppException;   
 22  
 23/**  
 24 * A collection of class management utility methods.  
 25 *   
 26 */
  
 27@SuppressWarnings("unchecked")   
 28public class ClassUtils {   
 29  
 30    /**  
 31     * 获得泛型类泛型参数类型.  
 32     * 例如:  
 33     * getGenericArgumentsType(List<String>.class)返回Class<String>.  
 34     * @param <T>  
 35     * @param cls  
 36     * @return  
 37     */
  
 38    public static <T> Class<T> getGenericArgsType(Class<?> cls) {   
 39        return getGenericArgumentsType(cls, 0);   
 40    }
   
 41  
 42    /**  
 43     * 获得泛型类泛型参数类型.  
 44     * @param <T>  
 45     * @param cls  
 46     * @param pos  
 47     * @return  
 48     */
  
 49    public static <T> Class<T> getGenericArgumentsType(Class<?> cls, int pos) {   
 50        return (Class<T>) ((ParameterizedType) cls.getGenericSuperclass()).getActualTypeArguments()[pos];   
 51    }
   
 52  
 53    /**  
 54     * 在指定的类路径查找符合条件的类.<br/>  
 55     * @param classPathPattern  
 56     * @param predicate  
 57     * @return  
 58     */
  
 59    public static Class<?>[] getClasses(String classPathPattern, Predicate predicate) {   
 60        PathMatchingResourcePatternResolver resolver = null;   
 61        resolver = new PathMatchingResourcePatternResolver();   
 62        MetadataReaderFactory metaFactory = null;   
 63        metaFactory = new CachingMetadataReaderFactory(resolver);   
 64        try {   
 65            Resource[] resources = resolver.getResources("classpath*:" + classPathPattern);   
 66            ArrayList<Class<?>> clazzArr = new ArrayList<Class<?>>();   
 67            for (Resource res : resources) {   
 68                if (!res.isReadable()) {   
 69                    continue;   
 70                }
   
 71  
 72                MetadataReader metadataReader = metaFactory.getMetadataReader(res);   
 73                String className = metadataReader.getClassMetadata().getClassName();   
 74                Class<?> clazz = ClassUtils.loadClass(className);   
 75                if (predicate.evaluate(clazz)) {   
 76                    clazzArr.add(clazz);   
 77                }
   
 78            }
   
 79            return clazzArr.toArray(new Class<?>[0]);   
 80        }
   
 81        catch (IOException e) {   
 82            throw new AppException(e);   
 83        }
   
 84        catch (LinkageError e) {   
 85            throw new AppException(e);   
 86        }
   
 87    }
   
 88  
 89    /**  
 90     * 在指定的类路径查找指定父类/接口类的所有子类.  
 91     * Example:  
 92     * Class<ITagChecker>[] checkerClz = ClassUtils.getSubClasses("com/linkage/ess/**<pre>/*</pre>.class", ITagChecker.class);  
 93     * @param <T>  
 94     * @param classPathPattern  
 95     * @param superClass  
 96     * @return  
 97     */
  
 98    public static <T> Class<? extends T>[] getSubClasses(String classPathPattern,   
 99            final Class<T> superClass) {   
100  
101        return (Class<? extends T>[]) getClasses(classPathPattern, new Predicate() {   
102            @Override  
103            public boolean evaluate(Object arg0) {   
104                Class<?> clazz = (Class<?>) arg0;   
105                return !clazz.isInterface() && superClass.isAssignableFrom(clazz);   
106            }
   
107        }
);   
108    }
   
109  
110    /**  
111     * Create a new instance given a class name(要求有默认构造函数).  
112     *   
113     * @param className  
114     *            A class name  
115     * @return A new instance  
116     * @throws ClassNotFoundException  
117     * @throws IllegalAccessException  
118     * @throws InstantiationException  
119     * @exception Exception  
120     *                If an instantiation error occurs  
121     */
  
122    public static <T> T newInstance(Class<T> clz) {   
123        try {   
124            return clz.newInstance();   
125        }
   
126        catch (InstantiationException e) {   
127            e.printStackTrace();   
128            throw new AppException(e);   
129        }
   
130        catch (IllegalAccessException e) {   
131            e.printStackTrace();   
132            throw new AppException(e);   
133        }
   
134  
135    }
   
136  
137    /**  
138     * 带有参数的实例创建.  
139     * @param <T>  
140     * @param impl  
141     * @param param  
142     * @param params  
143     * @return  
144     */
  
145    public static <T> T newInstance(Class<T> impl, Object params) {   
146        List<Class<?>> lstClass = new ArrayList<Class<?>>(params.length + 1);   
147        for (Object obj : params) {   
148            lstClass.add(obj.getClass());   
149        }
   
150        Class<?> paramClasses[] = lstClass.toArray(new Class<?>[0]);   
151  
152        return newInstance(impl, paramClasses, params);   
153    }
   
154  
155    /**  
156     * 带有参数的实例创建.  
157     * @param <T>  
158     * @param impl  
159     * @param paramClasses  
160     * @param params  
161     * @return  
162     */
  
163    public static <T> T newInstance(Class<T> impl, Class<?> paramClasses[], Object params[]) {   
164        try {   
165            Constructor<T> constructor = impl.getConstructor(paramClasses);   
166            return constructor.newInstance(params);   
167        }
   
168        catch (InstantiationException e) {   
169            e.printStackTrace();   
170            throw new AppException(e);   
171        }
   
172        catch (IllegalAccessException e) {   
173            e.printStackTrace();   
174            throw new AppException(e);   
175        }
   
176        catch (IllegalArgumentException e) {   
177            throw new AppException(e);   
178        }
   
179        catch (InvocationTargetException e) {   
180            throw new AppException(e);   
181        }
   
182        catch (SecurityException e) {   
183            throw new AppException(e);   
184        }
   
185        catch (NoSuchMethodException e) {   
186            throw new AppException(e);   
187        }
   
188    }
   
189  
190    /**  
191     * 使用类型的实例创建.(要求有默认构造函数).  
192     * @param className  
193     * @return  
194     */
  
195    public static Object newInstance(String className) {   
196        try {   
197            return loadClass(className).newInstance();   
198        }
   
199        catch (InstantiationException e) {   
200            e.printStackTrace();   
201            throw new AppException(e);   
202        }
   
203        catch (IllegalAccessException e) {   
204            e.printStackTrace();   
205            throw new AppException(e);   
206        }
   
207    }
   
208  
209    /**  
210     * Load a class given its name. BL: We wan't to use a known  
211     * ClassLoader--hopefully the heirarchy is set correctly.  
212     *   
213     * @param className  
214     *            A class name  
215     * @return The class pointed to by <code>className</code>  
216     * @exception ClassNotFoundException  
217     *                If a loading error occurs  
218     */
  
219    public static Class<?> loadClass(String className) {   
220        try {   
221            return getClassLoader().loadClass(className);   
222        }
   
223        catch (ClassNotFoundException e) {   
224            throw new AppException(e);   
225        }
   
226    }
   
227       
228    public static Method getMethod(String className,  String name, Class<?> parameterTypes) {   
229        return getMethod(loadClass(className), name, parameterTypes);   
230    }
   
231       
232    public static Method getMethod(Class<?> cls, String name, Class<?> parameterTypes) {   
233        try {   
234            return cls.getMethod(name, parameterTypes);   
235        }
   
236        catch (SecurityException e) {   
237            throw new AppException(e);   
238        }
   
239        catch (NoSuchMethodException e) {   
240            throw new AppException(e);   
241        }
   
242    }
   
243  
244    /**  
245     * Return a resource URL. BL: if this is command line operation, the  
246     * classloading issues are more sane. During servlet execution, we  
247     * explicitly set the ClassLoader.  
248     *   
249     * @return The context classloader.  
250     * @exception MalformedURLException  
251     *                If a loading error occurs  
252     */
  
253    public static URL getResource(String resource) {   
254        return getClassLoader().getResource(resource);   
255    }
   
256  
257    public static InputStream loadResource(String path) {   
258        try {   
259            return new ClassPathResource(path).getInputStream();   
260        }
   
261        catch (IOException e) {   
262            e.printStackTrace();   
263            throw new AppException(e);   
264        }
   
265    }
   
266  
267    /**  
268     * Return the context classloader. BL: if this is command line operation,  
269     * the classloading issues are more sane. During servlet execution, we  
270     * explicitly set the ClassLoader.  
271     *   
272     * @return The context classloader.  
273     */
  
274    public static ClassLoader getClassLoader() {   
275        return Thread.currentThread().getContextClassLoader();   
276    }
   
277  
278    public static Field getDeclaredField(Class<?> cls, String fieldName) {   
279        try {   
280            return cls.getDeclaredField(fieldName);   
281        }
   
282        catch (Exception e) {   
283            throw new AppException(e);   
284        }
   
285    }
   
286  
287    public static Object invokeQuietly(Object target, Method m) {   
288        try {   
289            return m.invoke(target);   
290        }
   
291        catch (IllegalArgumentException e) {   
292            e.printStackTrace();   
293        }
   
294        catch (IllegalAccessException e) {   
295            e.printStackTrace();   
296        }
   
297        catch (InvocationTargetException e) {   
298            e.printStackTrace();   
299            if (e.getTargetException() instanceof RuntimeException) {   
300                throw (RuntimeException) e.getTargetException();   
301            }
   
302        }
   
303  
304        return null;   
305    }
   
306}


----2010年08月31日
posted on 2010-09-01 12:43 李 明 阅读(442) 评论(0)  编辑  收藏 所属分类: 经验点滴

只有注册用户登录后才能发表评论。


网站导航: