2013-08-01 31 views
0

我发现一些辉煌的代码与30多个参数给一个方法(我失去了计数)。 如果/ then/else和开关块的实现包含超过500行重构帮助需要 - 与许多参数的方法

这怎么可能在一个干净的方式重构? 你的建议是什么?

大量的实现遍布整个应用程序,并全部推送这些参数。

问题的方法:

public static User findUser (
    String userCode, String lastName, String firstName, 
    String alternativeLastName, String sex, int day, int month, int year, 
    String locationParameter, String locationInfo, 
    Id groupId, Id organizationId, Id orderId, 
    Id orderGroupId, Id orderOrganizationId, 
    List<Id> groupIds, List<Id> organizationIds, 
    List<Id> orderIds, List<Id> orderGroupIds, 
    List<Id> orderOrganizationIds, 
    String timeRange, Long daysAgo, 
    Date dateFrom, Date dateUntil, 
    CodingMap codingMap, List<String> languageList, String visitType, 
    Account account, List<Group> accountGroups, 
    Organization accountOrganization, Profile profile, 
    AccessProfile accessProfile, Locale locale, int maxResults, 
    long newTimeRange, long minimumTimeRange, 
    boolean hideUserWithoutName, boolean withOrderInfo, boolean withVisitInfo, 
    boolean orderEntryAvailable, 
    boolean hideDiscontinuedResults, boolean checkPatientAccessRights, boolean searchForCopies, 
    boolean inOrderEntry, boolean allPatientCodes, 
    boolean addPatientCharacteristics, boolean showSpeciesColumn, 
    boolean patientDefinedWithPrivacyLevel, 
    boolean excludePatientsWithoutCodeInSelectedCodingSystem 
    ) throws CompanyException { 
... 
} 

用于所有的地方是这样的:

User.findUser(member.getCode(), context.lastName, context.firstName, 
    context.alternativeLastName, context.sex, 
    context.birthDate.getDay(), context.birthDate.getMonth(), 
    context.birthDate.getYear(), 
    context.locationParameter, context.locationInfo, 
    null, null, null, null, null, null, null, null, null, null, 
    session.timeRange(), session.daysAgo(), session.dateFrom(), 
    session.dateUntil(), 
    order.codingMap(), order.languageList(), member.visitType(), 
    null, null, null, null, null, locale, 25, 1000L,200L, 
    session.point.booleanValue(), session.infobooleanValue(), false, 
    true, true, true, true, true, true, true, false, false, false); 
+3

Ø...,M ...摹...... – assylias

+1

我的建议是** **运行。 –

+1

重构?我会称之为'重写'代码:D – Juvanis

回答

3

首先,我会先看看它的实际使用情况。

如果你发现它一再呼吁与这些参数的特定子集,你也许能够做这样的事情:正如其他人建议我将创建一个SearchParams

User.FindUserByABC(A, B, C) 
User.FindUserByXYZ(X, Y, Z) 

如果这是不适合的,类。所有属性将被初始化为默认值,它的使用将只涉及设置每个呼叫所需的相关搜索词,例如:

SearchParams params = new SearchParams(){A = "...", Z = "..."} 
User.FindUser(params) 

后者将肯定至少清理调用代码,影响最小的现有的基础机制。

0

我会与每个用户一个简单的主键的小SQL数据库替换此。

1

封装所有这些类中的参数

class MethodParam { 
     String userCode; String lastName; String firstName; 
     String alternativeLastName; String sex; int day; int month; int year; 
     String locationParameter; String locationInfo; 
     Id groupId; Id organizationId; Id orderId; 
     Id orderGroupId; Id orderOrganizationId; 
     List<Id> groupIds; List<Id> organizationIds; 
     List<Id> orderIds; List<Id> orderGroupIds; 
     List<Id> orderOrganizationIds; 
     String timeRange; Long daysAgo; 
     Date dateFrom; Date dateUntil; 
     CodingMap codingMap; List<String> languageList; String visitType; 
     Account account; List<Group> accountGroups; 
     Organization accountOrganization; Profile profile; 
     AccessProfile accessProfile; Locale locale; int maxResults; 
     long newTimeRange; long minimumTimeRange; 
     boolean hideUserWithoutName; boolean withOrderInfo; boolean withVisitInfo; 
     boolean orderEntryAvailable; 
     boolean hideDiscontinuedResults; boolean checkPatientAccessRights; boolean searchForCopies; 
     boolean inOrderEntry; boolean allPatientCodes; 
     boolean addPatientCharacteristics; boolean showSpeciesColumn; 
     boolean patientDefinedWithPrivacyLevel; 
     boolean excludePatientsWithoutCodeInSelectedCodingSystem; 
} 

,然后发送该类的方法

findUser(MethodParam param) { 
    .... 
} 

OR

把所有的PARAMS在地图中有明确定义的常量作为密钥

Map<String,Object> paramMap = new HashMap<>(); 
paramMap.put(Constants.USER_CODE, userCode); 

...

并接受地图作为参数

findUser(Map<String, Object> param) { 
     .... 
} 

至于if/else语句,开关而言,它们必须被分成逻辑小的子方法来降低复杂性cyclometric

2

您可以创建一个Predicate接口(或使用guava's):

interface Predicate<T> { boolean apply(T input); } 

的D本方法更改为:

User findUser(Predicate<User> p) { 
    //find user 
} 

你再这样称呼它:

findUser(new Predicate<User>() { 
    public boolean apply(User user) { 
     return member.getCode().equals(user.getCode()) 
       && user.lastname.equals(context.lastname); //etc. 
    } 
}); 

下一步可以使用流利的语法来轻松创建这些查询引入UserQuery。它会看起来像这样:

UserQuery query = new UserQuery(); 
query.lastname(context.lastname) 
     .code(member.getCode()); //etc 
Predicate<User> p = query.build(); 
User user = findUser(p); 
1

你最好创建一个包含所有这些参数的对象作为属性,并在整个代码中处理它。

public class MyObeject{ 
    String userCode, String lastName, String firstName, 
    String alternativeLastName, String sex, int day, int month, int year, 
    String locationParameter, String locationInfo, 
    Id groupId, Id organizationId, Id orderId, 
    Id orderGroupId, Id orderOrganizationId, 
    List<Id> groupIds, List<Id> organizationIds, 
    List<Id> orderIds, List<Id> orderGroupIds, 
    List<Id> orderOrganizationIds, 
    String timeRange, Long daysAgo, 
    Date dateFrom, Date dateUntil, 
    CodingMap codingMap, List<String> languageList, String visitType, 
    Account account, List<Group> accountGroups, 
    Organization accountOrganization, Profile profile, 
    AccessProfile accessProfile, Locale locale, int maxResults, 
    long newTimeRange, long minimumTimeRange, 
    boolean hideUserWithoutName, boolean withOrderInfo, boolean withVisitInfo, 
    boolean orderEntryAvailable, 
    boolean hideDiscontinuedResults, boolean checkPatientAccessRights, boolean searchForCopies, 
    boolean inOrderEntry, boolean allPatientCodes, 
    boolean addPatientCharacteristics, boolean showSpeciesColumn, 
    boolean patientDefinedWithPrivacyLevel, 
    boolean excludePatientsWithoutCodeInSelectedCodingSystem 
} 

findUser(MyObject obj); 

并只填写您需要在每种情况下的属性。我猜他们中的一些在某些情况下是可选的。

0

让建设者自我解释的制定者?我明白,30名制定者并不是更好,但至少可以通过编程方式生成它们。而且是否真的有这么多参数需要

2

建设者所有必要的参数创建方法类

public class FindUser { 
    // fields that represent necessary parameters 
    private final String lastName; 
    ... 

    // fields that represent optional parameters 
    private Id groupId; 
    ... 

    // builder class for necessary parameters 
    public static class Builder { 
     private String lastName; 
     ... 

     public Builder lastName(String lastName) { 
      this.lastName = lastName; 
      return this; 
     } 
     ... 

     public FindUser build { 
      return new FindUser(this); 
     } 
    } 

    // constructor taking a builder with all necessary parameters 
    private FindUser(Builder builder){ 
     // check here, whether all fields are really set in the builder 
     this.lastName = builder.lastName; 
     ... 
    } 

    // setters for all optional parameters 
    public FindUser groupId(Id groupId) { 
     this.groupId = groupId; 
     return this; 
    } 
    ... 

    // the action 
    public User compute() { 
     ... 
    } 
} 

复制前者方法体的方法类的新的计算方法里面。之后,您可以通过将许多代码块提取到自己的方法和类中来重构此方法。

最后两个步骤:

1)里面的老findUser方法,创建方法类的一个新对象,并调用计算方法。这不会减小参数列表的大小。

2)更改find​​User方法的所有用法以使用新的方法类,然后删除旧的findUser方法。

用法是:

FindUser fu = new FindUser.Builder() 
     .lastname("last name") 
     ... 
     .build() 
     .groupId(new GroupId()) 
     ...; 
User user = fu.compute();