Приветствую Вас Гость | RSS

ALLDev

Воскресенье, 03.12.2023, 14:49
Главная » Статьи » Программирование » Java

Пример использования fluent interface в java для описания объектов предметной области
В последнее время стало достаточно актуальным использование domain specific languages (DSL) — языков «заточенных» под конкретную предметную область. Слово «язык» в данном контексте не обязательно подразумевает именно новый язык программирования, зачастую можно обойтись и старым добрым.

Идея fluent interface в том, что API представляет собой некоторое подмножество домен-ориентированного языка описания. Причем это счастье доступно из базового языка программирования.

Текст Фаулера можно почитать по ссылке, я же приведу свой пример.

Допустим, нам нужно программно сконструировать объект соответствующий вот этому xml:
<Results>
 <unit>123</unit>
 <unit>321</unit>
 <ResultSet>
 <ResultsType>
 <ResultType>ABC</ResultType>
 <resAllTime>4.000000000000000</resAllTime>
 <resAllTime>5.000000000000000</resAllTime>
 <ResultsTimeBucket>
 <bucketDate>777</bucketDate>
 <value>3.000000000000000</value>
 <value>0.000000000000000</value>
 </ResultsTimeBucket>
 <ResultsTimeBucket>
 <bucketDate>888</bucketDate>
 <value>1.000000000000000</value>
 <value>5.000000000000000</value>
 </ResultsTimeBucket>
 </ResultsType>
 </ResultSet>
</Results> 


Смысл написанного в том, что у юнита 123 общее значение 4, которое складывается из 3 на дату 777 и еще 1 на дату 888. А у юнита 321 общее значение 5, которое целиком пришлось на дату 888.

API которое используется для построения такого объекта является надстройкой над плюсами (JNI):

Results r = new Results();
r.CallocResults(new int[] {123, 321}, new int[] {777, 888});
r.SetValue(4.0, "ABC", 0); // 0 - unit index in this case corresponds to "123"
r.SetValue(5.0, "ABC", 1);
r.SetBucketedValue(3.0, "ABC", 0, 0);
r.SetBucketedValue(1.0, "ABC", 1, 0); // 1 - bucketDate index (corresponds to 888), 0 - unit index
r.SetBucketedValue(5.0, "ABC", 1, 1);


В общем все по делу, придраться не к чему, но читать и представлять себе что будет в результате практически нереально …
Изначально это нужно было для юнит теста, поэтому использовать код с неочевидным результатом — не очень удачная идея, т.к. теряется наглядность юнит теста и его документирующая составляющая.

Я крепко подумал и попытался изобразить fluent interface для того же самого. Его реализация оказалась на удивление нетривиальной (из-за особенностей underlying JNI интерфейса), но зато выглядит он очень симпатично:

Results r = new ResultsBuilder()
 .withUnits(123, 321)
 .result("ABC")
 .value(123, 4.)
 .value(321, 5.)
 .on(777)
 .value(123, 3.)
 .on(888)
 .value(123, 1.)
 .value(321, 5.)
 .build(); 


В общем-то, освоив несколько приемов построения DSL на Java, задача становится технической: глаза боятся, руки делают.
Категория: Java | Добавил: artkil (10.11.2012)
Просмотров: 1443 | Теги: fluentinterface, java, DSL, martin fowler | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *: