Дизайн интерфейса
От: Воронков Василий Россия  
Дата: 12.06.09 12:02
Оценка:
Итак, задача — система, позволяющая создавать пользовательские функции для SQL-БД. Функции пишутся на дотнете. Функции бывают двух видов — скалярные и агрегаты. Допускается перегрузка функций. Агрегаты фактически представляют собой две функции — одна вызывается по ходу вычислений, а другая только один раз, в конца (таков дизайн БД, я тут не причем).
Пока останавливаюсь на таком:

1. Для создания собственной функции необходимо реализовать интерфейс IFunction. На настоящий момент интерфейс получает универсальным — и для скалярных, и для агрегатов:

public interface IFunction
{
  void Execute(CallType call, IFunctionContext context);
}


CallType — энумерация, которая показывает, в каком качестве вызывается функция:

public enum CallType
{
  Normal,
  Step,
  Final
}


С одной стороны вроде и неплохо. С другой — как-то не очень. Во-первых, единственный смысл этой функции отличить вызов "обычной" скалярной функции от одного из вызовов в цепочке агрегата. Далее — единственный интерфейс для функций, принцип работы которых сильно отличается тоже не очень.
Логически высматривается такая картинка:

IFunction -> IScalarFunction
          -> IAggregateFunction


И регистрация функций будет выглядеть красиво. Но, во-первых, IFunction получается пустым. Ну просто нечего туда засунуть. И как-то некрасиво это. Во-вторых интерфейсы тоже выглядят довольно странно:

public interface IScalarFunction : IFunction
{
  void Execute(IFunctionContext context);
}

public interface IAggregateFunction : IFunction
{
  void Execute(CallType call, IFunctionContext context);
}


Не знаю, может, это только я, но как-то глаз колит.

2. Далее. Как вы заметили, есть такая штука как IFunctionContext. Причем очень даже важная штука, вот как она выглядит:

public interface IFunctionContext
{
  Variant GetParameter(int index);
  void SetResultValue<T>(T value) where T : IConvertible;
  void SetResultBlob(byte[] buffer);
  void SetResultNull();
  void SetResultZeroBlob(int length);
  void ReportError(FunctionError error);
  void ReportError(int code, string message);
}


Изящно, не правда ли? Предназначение этого интерфейса, думаю, вполне понятно по объявлению, но уже как-то он "смешивает напитки". Хотелось бы как-то это поменять...

Заранее оговорюсь, что регистрацию через лямбду я не рассматриваю, т.к. на мой взгляд это весьма частный случай и далеко не весь код будет выглядеть понятно и красиво при передаче лямбды. Поэтому мне кажется, что регистрация через лямбду должна быть реализована как "фишка" поверх описываемой здесь инфраструктуры.

Пока все. Буду рад любым советам.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.