近日有人问起,“你认为如何能提高代码的质量”,虽然都说出来了,但缺乏条理,特总结于此。
首先,应明确什么样的代码算是质量高的。然后才能知道如何去做。
我觉得,高质量的代码应该至少包括:
1.可读性。
2.可维护性。
代码的可读性同样有助于代码的可维护性。有时候在一个项目里,你修改的代码未必是自己写的,如果代码写的可读性很差,那将是非常痛苦的。
一、可读性
1.包名、类名、成员变量名、方法名、局部变量名等的命名应仔细斟酌。尽量做到读一段代码,就像是读一句话一样,在阅读的过程中就能理解其中的逻辑。
2.包下面应包含哪些类,这也是有讲究的。不能太随意。从包中应该可以大概看出类的功能或所在层次。
3.一个方法只要实现一个功能。这一点很重要,首先利于阅读,方法的名字可以告诉你它的功能。
4.方法的实现不宜过长,个人写代码的习惯是,一个方法的长度不会超过电脑的一屏。也就是不用拖动滚动条便可把实现尽收眼底。
二、可维护性
1.代码写的要灵活,尤其是一些配置文件。比如写一个下载程序,文件的放置路径就不能在代码中写死。因为一来以后要变动的话,还要来改程序,并重新部署;二来开发的环境与正式的环境有所不同,写死也不利于部署。
最典型的例子就是数据库的连接信息,url、用户名、密码等,开发环境与正式环境一般不会相同,把这些信息写在配置文件里为好。
2.提高的代码复用,以提高代码的维护性。
举个反例吧。我们的系统中有很多生成Excel文件并在浏览器端下载的功能要求,由于这些功能由不同的人来完成,结果类似的程序写了二十几份,都是互相拷贝而来。
当时我们用的是POI的低版本,后来进行了POI的升级,有一些API不能使用了,于是改了二十几个类。如果把这些功能复用一些,也许只要修改一个类文件就搞定了。
3.多用一些设计模式,提高代码的层次感。使得修改代码的时候,影响范围达到尽量的小。这个就有难度了。平时要慢慢积累才行。
常用的模式 工厂模式、模板模式、适配器模式、策略模式、代理模式(动态代理) 等。这些模式在平时的工作中经常用到,应该熟练运用才行。
下面是一些代码片段:
1
private 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
13
private 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
23
private boolean replace(JobConfig original, JobConfig job)
{
24
return remove(original) && schedule(job);
25
}
26
27
private 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
38
private 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
1
import java.io.IOException;
2
import java.io.InputStream;
3
import java.lang.reflect.Constructor;
4
import java.lang.reflect.Field;
5
import java.lang.reflect.InvocationTargetException;
6
import java.lang.reflect.Method;
7
import java.lang.reflect.ParameterizedType;
8
import java.net.MalformedURLException;
9
import java.net.URL;
10
import java.util.ArrayList;
11
import java.util.List;
12
13
import org.apache.commons.collections.Predicate;
14
import org.springframework.core.io.ClassPathResource;
15
import org.springframework.core.io.Resource;
16
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
17
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
18
import org.springframework.core.type.classreading.MetadataReader;
19
import org.springframework.core.type.classreading.MetadataReaderFactory;
20
21
import com.lim.base.exception.AppException;
22
23
/** *//**
24
* A collection of class management utility methods.
25
*
26
*/
27
@SuppressWarnings("unchecked")
28
public 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日