2

我有一个客户端(Android 应用程序)和一个服务器(WebApi REST Web 服务)。

该应用程序有一个服务层,它调用它来与 Web 服务通信以读取和写入记录。返回值从 Web 服务的控制器发回(即,当新记录写入数据库并生成相关的记录 ID 时)。

我有许多不同的控制器,每个控制器都有多个方法,它们都返回不同数量和类型的值(它们大多返回 int 数组,但如果混入非整数值,偶尔我会返回一个对象数组)。

应用程序端的服务层会进行一些检查以验证参数,例如检查参数计数(数组元素)和检查预定义的无效/未初始化值(如 -9999)。

我不想通过定义一个接口来形式化这些参数操作,以便在一个位置明确指定双方使用的参数的计数和类型(所以我不是在双方都“摇摆不定”)。

然而,我遇到的困境是决定是定义一个接口来指定客户端和服务器相关的方法,还是定义两个单独的接口,每个接口都指定特定于通信的那一侧的方法。

如果我有一个界面,像这样:

public interface IServiceParams
{
   object[] CreateParams(int recordId, string recordNumber);

   bool ParseParams(object[] paramz, out int recordId, out string recordNumber);
}

那么由于 CreateParams 仅在 WS 端使用,而 ParseParams 在 App 端使用,我将不得不在任一端声明空实现

Web服务端:

public class RecordController : ApiController, IServiceParams
{
   object[] IServiceParams.CreateParams(int recordId, string recordNumber)
   {
      return new[] { newRecordId, newRecordNumber };
   }

   bool IServiceParams.ParseParams(object[] paramz, out int recordId, out string recordNumber)
   {
      throw new NotImpementedException();
   }

   ////////////////////////////////////////////////////////////////////////////////////////////

   public object[] Put( Record record )
   {
      if( !DbLayer.Update(record) )
      {
         return null;
      }

      return CreateParams(record.RecordId, record.RecordNumber);
   }
}

应用端:

public class RecordService : IServiceParams
{
   object[] IServiceParams.CreateParams(int recordId, string recordNumber)
   {
      throw new NotImpementedException();
   }

   bool IServiceParams.ParseParams(object[] paramz, out string recordNumber)
   {
      if( paramz == null || paramz.Count != 4 )
      {
         return false;
      }

      if(!ParseInt(paramz[0].ToString(), out recordId) || recordIdNew == DEFAULT_RECORD_ID)
      {
         return false;
      }

      // ...

      return true;
   }

   ////////////////////////////////////////////////////////////////////////////////////////////

   public bool UpdateRecord( Record record )
   {
      object[] paramz = WebService.Put( record );

      int recordId; 
      string recordNumber;

      if(!ParseParams(paramz, out recordId, out recordNumber))
      { 
         return false;
      }

      record.RecordId = recordId;
      record.RecordNumber = recordNumber;

      return true;
   }
}    

或者,我是否应该定义两个接口,并在各自的侧面实现每个接口,从而消除空实现的需要:

public interface IServiceParamsClient
{
   bool ParseParams(object[] paramz, out int recordId, out string recordNumber );
}

public interface IServiceParamsServer
{
   object[] CreateParams(int recordId, string recordNumber);
}

非常感谢您的帮助!

4

2 回答 2

2

是否有任何理由需要在一个接口中声明这两种方法?如果没有,请制作两个独立的界面,每个界面都反映了他们的意图。必须实现“不支持”的方法是一种设计气味。请参阅: 当我的操作并非所有实现者都支持时,设计界面的正确方法是什么?

于 2013-10-22T16:45:50.357 回答
1

进行两个界面设计。通过这样做,您可以使用更简洁的 API 帮自己一个忙。一个建议是您可以将参数逻辑封装在一个类中,这样现在您就有了更强大的静态检查类型,这不是一件小事。其次,我不确定Web服务了解App客户端是否是一件好事。我认为应该反过来。所以我会这样做:

public class Param //at server side
{
   public int recordId { get; set; }
   public int transToPropId { get; set; }
   public int receivedViaTypeId { get; set; }
   public string recordNumber { get; set; }
}

public interface IParamParser //at client
{
   //I do not know what object[] paramz is; I leave that to you; 
   //may be it needs encapsulation as well
   bool Parse(object[] paramz, Param p);
}

public interface IParamCreator //at server
{
   Param CreateParams(int recordId, int transToPropId, int receivedViaTypeId, 
                      string recordNumber);
}
于 2013-10-22T17:33:33.537 回答