0

メソッドに 30 を超えるパラメーターが指定されている素晴らしいコードを見つけました (カウントを失いました)。実装には、 if/then/elseおよびswitchブロックを含む 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);
4

7 に答える 7

3

まず最初に、実際の使用法をもう少し詳しく調べます。

これらのパラメーターの特定のサブセットで繰り返し呼び出されることがわかった場合は、次のようなことができる場合があります。

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

これが適切でない場合は、他の人が示唆しているように、SearchParamsクラスを作成します。すべてのプロパティはデフォルト値に初期化され、その使用には、各呼び出しに必要な関連検索用語の設定のみが含まれます。

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

後者は、既存の基礎となるメカニズムへの影響を最小限に抑えて、少なくとも呼び出しコードを確実にクリーンアップします。

于 2013-08-01T09:27:13.130 に答える
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() {
        ...
    }
}

メソッド クラスの新しい compute メソッド内に以前のメソッド本体をコピーします。その後、コードの多くのチャンクを独自のメソッドやクラスに抽出することで、このメソッドをリファクタリングできます。

最後の 2 つの手順:

1) 古い findUser メソッド内で、メソッド クラスの新しいオブジェクトを作成し、compute メソッドを呼び出します。これにより、パラメーター リストのサイズが縮小されることはありません。

2) findUser メソッドのすべての使用箇所を新しいメソッド クラスを使用するように変更してから、古い findUser メソッドを削除します。

使用法は次のとおりです。

FindUser fu = new FindUser.Builder()
        .lastname("last name")
        ...
        .build()
        .groupId(new GroupId())
        ...;
User user = fu.compute();
于 2013-08-01T10:08:04.667 に答える