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 李 明 閱讀(452) 評論(0)  編輯  收藏 所屬分類: 經驗點滴

          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 荆州市| 雷州市| 黑水县| 平武县| 五原县| 元阳县| 资阳市| 蒙城县| 安徽省| 武义县| 唐山市| 山东| 辽宁省| 象山县| 通榆县| 泸定县| 乐至县| 介休市| 静宁县| 扎兰屯市| 赤城县| 望城县| 房山区| 星子县| 洛隆县| 左云县| 阿拉善盟| 广饶县| 名山县| 鲁甸县| 崇礼县| 怀安县| 建平县| 康平县| 义乌市| 海淀区| 西和县| 贵阳市| 南华县| 金寨县| 通州区|