【设计】一个有意思的服务方法入参设计

今天晚上和项目组的几个同学讨论一个服务方法的入参设计,觉得挺有意思的,在此记录一下!

 

背景

我们的场景需要对外暴露一个远程服务写入接口,用于给几个外部同步数据的场景。

由于历史的原因,需要被写入的这个业务对象很大,字段很多(100多个字段,也会涉及多个表)。

以下是场景提取出来的一些要求:

1.这个场景只需要同步更新几个字段到该主表里。为了数据安全和方便理解,不希望把整个业务对象暴露出来,希望只暴露几个该场景可以写入的字段。

2.外部场景都是能拿到该业务对象的唯一外键的,所以为了交互友好,不希望流程是"远程读取数据-->修改数据-->远程更新数据",而希望是"拼装需要同步的数据-->远程同步"的流程。

 

注:用的是公司内部应用的的java远程调用服务框架,只在java语言内部调用。只考虑java 语言层面的设计,不考虑soap这些重量级的方案。

入参的设计方案

方案一

一开始想得是设计一个只包含可更新字段的pojo model类作为入参。如:

public class WritableModel {
	String property1;
	String peoperty2;
	public String getProperty1() {
		return property1;
	}
	public void setProperty1(String property1) {
		this.property1 = property1;
	}
	public String getPeoperty2() {
		return peoperty2;
	}
	public void setPeoperty2(String peoperty2) {
		this.peoperty2 = peoperty2;
	}
	
}

 这个model强类型固然好,但是有一个很难避免的问题就是二义性。

在property1为null的时候,是说明不更新这个字段还是要清空这个字段呢?(注意:在这里的写场景里这两种情况都需要支持!)

强类型虽然约束了可更新范围,这个时候pojo里的null是没办法去理解。

 

方案二

由于方案一的缺陷根本就没办法满足需求,于是想了下用map来作为入参,但是map是弱类型,我们必须定义一些key,并让调用方只用这个key。于是想到了将key用一个枚举来表示,然后入参用java map泛型来约束.

如下:

key的枚举类设计如下:

public enum WritablePropertyType {
	PROPERTY1_NAME//属性1的名字
	, PROPERTY2_NAME//属性2的名字
}

 服务方法入参设计如下:

	/**
	 * 
	 * @param map  需要被同步的字段
	 * @return 是否成功
	 */
	public boolean sync(Map<WritablePropertyType,Object> map);

以上虽然很简洁,对于调用者只需要将自己需要更新的字段拼装成map,同时key使用WritablePropertyType 泛型约束。如果需要对某个字段清空,只需要put一个null值进来就行了。

但是泛型约束并不那么强,对于不遵循泛型的map的入参虽会有警告但是没办法做到强类型的约束,还是存在一些风险。难道在服务端进行key类型检查,不规范的抛异常吗?为了更好的约束,又有了方案三。

 

方案三

方案二随能很好满足需求,但是泛型毕竟约束是不够的,于是想了方案三。基本是延续方案二的思路,用map。也是由自己设计的WritablePropertyType 枚举作为map的key。但是要对map做一些改造,使得map只能放进来以WritablePropertyType作为key的map。于是想到对HashMap做一个扩展,只是简单的复写put方法,并在put方法里强制检查。

复写的map如下:

import java.util.HashMap;

public class WritableMap<K, V> extends HashMap<K, V> {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public V put(K key, V value) {
		if (key instanceof WritablePropertyType) {//强制检查
			super.put(key, value);
			return value;
		} else {
			throw new IllegalArgumentException(
					"key type must be WritablePropertyType");
		}
	}
}
 

 服务方法入参设计如下:

	/**
	 * 
	 * @param map  需要被同步的字段
	 * @return 是否成功
	 */
	public boolean sync(WritableMap<WritablePropertyType,Object> map);

 

 

 

 

以上方案三是最后定下来一个折中的方案,相信这还不是最优方案,不知道大家有没有更好的方案?说说你的观点吧,:)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值