この記事では、クエリを繰り返してプロジェクトを再構築する方法について説明します。コードの可読性と保守性を向上させます。主に関連する電力会社の注文との情報システムを照会するために使用されるコードを見て:
public class Order {
public static final int PAY_TYPE_WECHAT = 1;
public static final int PAY_TYPE_ALIPAY = 2;
public static final int PAY_TYPE_UNIONPAY = 3;
//实际支付金额
private int payValue;
//实际支付时间
private long payTime;
//实际支付类型 1 微信支付 2支付宝支付 3银联支付
private int type;
//支付过程是否使用了贷款
private boolean useLoan;
//下面省略一堆get set方法
}
复制代码
次に、注文処理システムの結果があります。
public class OrderFinder {
private List<Order> orders = new ArrayList<>();
//新增一笔订单
public void addOrder(Order order) {
orders.add(order);
}
//返回没有使用过贷款的订单
public List<Order> getNoUseLoan() {
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (!order.isUseLoan()) {
orders.add(order);
}
}
return orders;
}
//返回在这个日期之前的订单
public List<Order> beforDate(long date) {
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (order.getPayTime() < date) {
orders.add(order);
}
}
return orders;
}
//返回在这个日期之前 且金额大于固定值的 的订单
public List<Order> beforDateAndOverValue(long date, int payValue) {
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (order.getPayTime() < date && order.getPayValue() > payValue) {
orders.add(order);
}
}
return orders;
}
//返回大于这个支付金额 并且是使用微信支付的订单
public List<Order> overPayAndUseWechat(int payValue) {
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (order.getPayValue() > payValue && order.getType() == PAY_TYPE_WECHAT) {
orders.add(order);
}
}
return orders;
}
}
复制代码
I上記のコードは、多くの人々は、上記のコードのどのような欠点の集計を聞かせて、古いクラス内のいくつかの古いプロジェクトで遭遇することになると思います。
- あまりにも多くの重複したコードは、メンテナンスが困難だった後、多くの場所を変更する必要があり、重複したコード内に露出しすぎパブリッククエリメソッドを見ることができます。
- あなたは新たな需要、新しい条件を追加する必要性に来た場合、私たちは重複したコードの束を書き換える必要があり、このような上記のシステムとして、特定の日付や順序は、マイクロチャネルの賃金を使用することである前に、私はリターンを要求しました。
- 関数本体内のステートメントは硬すぎるシステム時刻が、私たちはかなり明確な関数の名前を書くように、これはデモですが、クエリが複雑であるか、古いシステムのコードを記述する際にどのように特定のクエリ、一目で確認することは困難であるとき、もう少し複雑な、悪い時には、多くの場合、関数名によって、特定のクエリ条件知られていない、何をすべきかを知りませんでした定期的に読んで関数ソースに、この時間を。
痛みのポイントを解決するために、我々はいくつかの再構築を行い、次のように、私たちが解決しなければならない痛みの再建、この時点では次のとおりです。
- 上記のコード内の重複コードの除去
- 新たな需要の大半は、単一のクエリを追加せずに、組み合わせの形で書くことができます
- 読みやすく、メンテナンスの容易さ
これらのニーズに私たちの最初の応答、トレースを実施する - これらのクエリ:
//查询的基类
public abstract class Spec {
public abstract boolean isFitByCondition(Order order);
}
//早于这个时间的
public class BeforeDateSpec extends Spec {
private long date;
public BeforeDateSpec(long date) {
this.date = date;
}
@Override
public boolean isFitByCondition(Order order) {
return order.getPayTime() < date;
}
}
//不使用贷款的
public class NoLoanSpec extends Spec {
@Override
public boolean isFitByCondition(Order order) {
return !order.isUseLoan();
}
}
//超过一定金额的
public class OverPaySpec extends Spec {
public OverPaySpec(int value) {
this.value = value;
}
private int value;
@Override
public boolean isFitByCondition(Order order) {
return order.getPayValue() > value;
}
}
//使用微信支付的
public class UseWechatSpec extends Spec {
@Override
public boolean isFitByCondition(Order order) {
return order.getType() == Order.PAY_TYPE_WECHAT;
}
}
//组合查询
public class AndSpec extends Spec {
public AndSpec(Spec augEndSpec, Spec addEndSpec) {
this.augEndSpec = augEndSpec;
this.addEndSpec = addEndSpec;
}
private Spec augEndSpec;
private Spec addEndSpec;
@Override
public boolean isFitByCondition(Order order) {
return augEndSpec.isFitByCondition(order) && addEndSpec.isFitByCondition(order);
}
}
复制代码
このクエリでは、我々は、メインクラスを見に変更することができます。
public class OrderFinder2 {
private List<Order> orders = new ArrayList<>();
//新增一笔订单
public void addOrder(Order order) {
orders.add(order);
}
//返回没有使用过贷款的订单
public List<Order> getNoUseLoan() {
Spec spec = new NoLoanSpec();
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (spec.isFitByCondition(order)) {
orders.add(order);
}
}
return orders;
}
//返回在这个日期之前的订单
public List<Order> beforDate(long date) {
Spec spec = new BeforeDateSpec(date);
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (spec.isFitByCondition(order)) {
orders.add(order);
}
}
return orders;
}
//返回在这个日期之前 且金额大于固定值的 的订单
public List<Order> beforDateAndOverValue(long date, int payValue) {
Spec spec1 = new BeforeDateSpec(date);
Spec spec2 = new OverPaySpec(payValue);
AndSpec andSpec = new AndSpec(spec1, spec2);
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (andSpec.isFitByCondition(order)) {
orders.add(order);
}
}
return orders;
}
public List<Order> overPayAndUseWechat(int payValue) {
Spec spec1 = new UseWechatSpec();
Spec spec2 = new OverPaySpec(payValue);
AndSpec andSpec = new AndSpec(spec1, spec2);
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (andSpec.isFitByCondition(order)) {
orders.add(order);
}
}
return orders;
}
}
复制代码
、我々は基本的には読みやすさを完了し、ホットスワップ可能な特徴の第二版では、上記の変化、を見て長いことができますようにとスペックと組み合わせて新しいクエリ、後に、書き込みクエリを繰り返す必要がありますが、これは明らかにされていません完璧ではない、私たちは復興を継続するようなので、多くのイテレータを持っているコードを繰り返します。
public class OrderFinder3 {
private List<Order> orders = new ArrayList<>();
//新增一笔订单
public void addOrder(Order order) {
orders.add(order);
}
//注意这个函数是private的
private List<Order> selectBy(Spec spec) {
List<Order> orders = new ArrayList<>();
Iterator iterator = orders.iterator();
while (iterator.hasNext()) {
Order order = (Order) iterator.next();
if (spec.isFitByCondition(order)) {
orders.add(order);
}
}
return orders;
}
//返回没有使用过贷款的订单
public List<Order> getNoUseLoan() {
return selectBy(new NoLoanSpec());
}
//返回在这个日期之前的订单
public List<Order> beforDate(long date) {
return selectBy(new BeforeDateSpec(date));
}
//返回在这个日期之前 且金额大于固定值的 的订单
public List<Order> beforDateAndOverValue(long date, int payValue) {
return selectBy(new AndSpec(new BeforeDateSpec(date), new OverPaySpec(payValue)));
}
public List<Order> overPayAndUseWechat(int payValue) {
return selectBy(new AndSpec(new UseWechatSpec(), new OverPaySpec(payValue)));
}
}
复制代码
ここでは、基本的に再構築を完了しました。そして、このような変化の本質はあまり大きくない(しかし、効果は良いですが)、常に最適化するためのデザインパターンの様々なとは思わない、コーディング成熟したシステムでは、テストの広い範囲に影響を与え、将来的に大きな変化を心配していないが大モジュールの数が、小さなクラスまたは関数のエントリからの範囲であるべきであるが、小さな再構成モジュールを支え、システム全体の最適化の最終的な目的を達成するために、。
この記事では、シーンはこのビジネスシナリオ「クエリ」の実用化に厳格に固執する必要はありませんそして、あなたはあなたのクラスが重複したコードのほとんどを持っている外部関数の多くの機能を提供することを発見した場合や、条件が組み合わされて再構築され、このようなアプローチを利用することができます。