Нужен совет по многословному названию методов - PullRequest
5 голосов
/ 10 марта 2009

Я пишу API для создания геометрических фигур и сталкиваюсь с некоторыми трудностями, называя свои методы.

Давайте рассмотрим простой случай: создание круга. Большинство из нас могут быть знакомы с методом, подобным graphics.drawEllipse(x, y, w, h). Чтобы нарисовать круг, вам нужно знать верхнюю левую координату, а также ширину и высоту круга.

Мой API предназначен для того, чтобы разработчик мог с легкостью рисовать фигуры, используя разнообразную информацию, не прибегая к математике, что тривиально для кругов, но сложнее для других фигур. Например, вы также должны иметь возможность нарисовать окружность, учитывая ее центральные координаты и радиус или верхнюю левую и нижнюю правую координаты.

Итак, у меня есть Circle класс с фабричными методами, такими как: Circle.createWithCenterAndRadius(cx, cy, r) Circle.createWithBoundingBox(x1, y1, x2, y2) Circle.createWithWidthAndHeight(x, y, w, h)

Я чувствую, что здесь может быть "запах кода", но я не уверен. С одной стороны, эти фабричные методы обязательно носят описательный характер. С другой стороны, я могу предвидеть, что названия этих методов выйдут из-под контроля. Например, как бы я назвал метод фабрики треугольника, который создает треугольник с заданной точкой, длиной одной стороны, углом и длиной другой стороны? Triangle.createWithPointSideAngleAndSide(x, y, side1, angle, side2)? Это просто зло?

Если бы вы использовали этот API, были бы вам хороши такие имена методов? У вас есть совет, как я могу сделать имена методов более разумными?

Ответы [ 9 ]

14 голосов
/ 10 марта 2009

Вы можете изменить свои методы круга на

Circle.FromCenterAndRadius(...)
Circle.FromBoundingBox(...)
Circle.FromWidthAndHeight(...)

Это подразумевает, что вы создаете круги из их разных представлений в некотором сжатом виде ...

11 голосов
/ 10 марта 2009

Это нормально для любого языка, который не поддерживает именованные параметры. Если язык поддерживает именованные параметры, мне больше нравится короткий Create и просто есть очевидные имена параметров.

Для языка с именованными параметрами вы должны:

Circle.Create(
   centerX = cx, 
   centerY = cy, 
   radius = r
);

Еще один более сложный вариант, такой как свободный интерфейс (но это, вероятно, слишком много):

circleBuilder.Center(cx,cy).Radius(r)
circleBuilder.Center(x,y).Width(w).Height(y)
circleBuilder.BoundWith().Left(x1,y1).Right(x2,y2)

Центр возвращает экземпляр промежуточного класса, который допускает только радиус или ширину. И BoundWith возвращает тот, который разрешает только Left.

8 голосов
/ 10 марта 2009

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

Вы также можете применить некоторый шаблон проектирования здесь, если вы действительно беспокоитесь о представлении большого количества фабричных методов - например, наличие фабричных методов с классами свойств. У вас может быть класс CircleProperties со свойствами, такими как CenterX, CenterY, Radius, (bool) UseCenterX, (bool) UseCenterY и т. Д., А затем вы передаете его общедоступному методу фабрики, который выяснит, какой (частный) метод фабрики использовать.

Предполагая C #:

var circleProperties = new CircleProperties()
{
   CenterX = 10,
   CenterY = -5,
   Radius = 8,
   UseCenterX = true,
   UseCenterY = true,
   UseCenterRadius = true
};

var circle = Circle.Create(circleProperties);
6 голосов
/ 10 марта 2009

Мой первый инстинкт - иметь больше типов, что позволило бы более интуитивно перегружать методы.

// instead of Circle.createWithCenterAndRadius(cx, cy, r)
Circle.create( new Point(cx,xy), r);

// instead of Circle.createWithBoundingBox(x1, y1, x2, y2)
Circle.create( new Point(x1,y1), new Point(x1,y1) );
// or even...
Circle.create( new Box(p1,p2));

// instead of Circle.createWithWidthAndHeight(x, y, w, h)
Circle.create( new Point(x,y), w, h);

Так же, как и Point, вы можете определить расстояние (которое учитывает разные единицы)

Если этот стиль вам подходит, подумайте, зачем вам нужен фабричный метод вместо конструктора.

Circle c = new Circle(new Point(cx,xy), r);
1 голос
/ 10 марта 2009

У меня были бы методы CreateTriangle, и перегрузки показывали бы различную необходимую информацию.

* 1003 Е.Г. *

Circle.CreateCircle(cx, cy, r)
Circle.CreateCircle(point1, point2)
Circle.CreateCircle(point, width, height)
1 голос
/ 10 марта 2009

Для языков, которые не поддерживают именованные параметры, было бы удобнее сделать имя метода очень простым, например Circle.create , а затем просто добавить дополнительную строку входного флага (например, "center" или «ограничивающий»), который указывает, как следует интерпретировать входные значения для случаев, которые трудно различить, основываясь только на номере и типе входной переменной? Недостатки этого заключаются в том, что требуется дополнительная логика внутри метода для обработки различных типов входных аргументов, а также требует, чтобы пользователь запомнил параметры флага.

0 голосов
/ 06 апреля 2009

Ваш инстинкт верен - весь шаблон создания вещей таким образом - ненадежный.

Если только они не используются один или два раза, они станут довольно грязными. Если бы вы создавали фигуру из 5 кругов и 3 треугольников, это было бы беспорядком.

Все, что не является тривиальным примером, вероятно, лучше всего сделать с какой-то реализацией, управляемой данными.

Для этих целей очень полезно иметь строку, хэш или XML для определения ваших фигур.

Но все зависит от того, как вы ожидаете их использовать.

У меня такие же проблемы с созданием элементов управления Swing в Java. В итоге вы получаете строку за строкой «new Button ()», за которой следует набор вызовов свойств .set, а также строка кода для копирования значения в объект (или добавления прослушивателя) и строка для сброса значение ..

Такого рода шаблон никогда не должен встречаться в коде, поэтому я обычно пытаюсь найти способ использовать его с данными, динамически привязывать элементы управления к объектам - и для этого очень полезен описательный язык на основе строк .

0 голосов
/ 10 марта 2009

Я знаю, я знаю. Это звучит совершенно безумно для вас, C / C ++ / Java, но примеры, приведенные в вопросе и во всех этих ответах, ясно демонстрируют, что такое плохое, плохое соглашение CamelCaseNaming.

Давайте еще раз посмотрим на оригинальный пример:

Circle.createWithCenterAndRadius(cx, cy, r)  
Circle.createWithBoundingBox(x1, y1, x2, y2)
Circle.createWithWidthAndHeight(x, y, w, h)

А теперь давайте избавимся от обозначения случая с верблюдом

Circle.create_with_center_and_radius(cx, cy, r)  
Circle.create_with_bounding_box(x1, y1, x2, y2)
Circle.create_with_width_and_height(x, y, w, h)

Это может показаться ужасно незнакомым, но, честно говоря, какую версию легче читать?

0 голосов
/ 10 марта 2009

Да, это скорее мета-ответ, но я предлагаю вам взглянуть на то, как происходит именование в Apple's Cocoa .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...