需要有关方法的冗长命名的建议

发布于 2024-07-14 14:51:57 字数 813 浏览 5 评论 0原文

我正在编写一个用于创建几何形状的 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,您可以接受这样的方法名称吗? 您对如何使方法名称更合理有什么建议吗?

I'm writing an API for creating geometric shapes, and I'm running into some difficulties naming my methods.

Let's take a simple case: Creating a circle. Most of us might be familiar with a method like graphics.drawEllipse(x, y, w, h). To draw a circle, you need to know the top left coordinate, and the width and height of the circle.

My API is intended to make it easy for a developer to draw shapes using a variety of information, without doing a lot of math - which is trivial for circles, but more complicated for other shapes. For example, you should also be able to draw a circle given its center coordinates and radius, or the top left and bottom right coordinates.

So I have a Circle class with factory methods like:

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

I feel like there might be a "code smell" here, but I'm not sure. On the one hand, these factory methods are necessarily descriptive. On the other hand, I can forsee these method names getting out of control. For example, how would I name a Triangle factory method that creates a triangle given a point, the length of one side, an angle, and the length of another side? Triangle.createWithPointSideAngleAndSide(x, y, side1, angle, side2)? Is that just evil?

If you were to use this API, would method names like this be okay to you? Do you have advice on how I can make the method names more sane?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

北斗星光 2024-07-21 14:51:57

您可以将您的圆圈方法更改为

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

这意味着您正在以一种简洁的方式从不同的表示形式创建圆圈......

You might change your circle methods to

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

It implies that you're creating circles from their different representations in a kind of concise way...

吻安 2024-07-21 14:51:57

在任何不支持命名参数的语言中都可以。 如果语言支持命名参数,我更喜欢简短的 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)

Center 返回仅允许 Radius 或 Width 的中间类的实例。 BoundWith 返回一个只允许 Left 的值。

It is ok in any language that doesn't support named parameters. If the language supports named parameters, I like more the short Create and just have obvious parameters names.

For a language with named parameters, you would:

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

Another more involved option, would be a fluent interface like (but that is probably too much):

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

Center returns an instance of an intermediate class that only allows Radius or Width. And BoundWith returns one that only allows Left.

韵柒 2024-07-21 14:51:57

我认为你的描述方法没有任何问题——它们很紧凑,并且准确地描述了正在发生的事情。 库的用户和维护程序员都不会怀疑您的方法的功能。

如果您确实担心暴露大量工厂方法(例如具有属性类的工厂方法),您也可以在这里应用一些设计模式。 您可以拥有一个具有 CenterX、CenterY、Radius、(bool)UseCenterX、(bool)UseCenterY 等属性的 CircleProperties 类,然后将其传递给公共工厂方法,该方法将确定要使用哪个(私有)工厂方法。

假设 C#:

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

var circle = Circle.Create(circleProperties);

I think there is nothing wrong with your descriptive methods - they are the compact and describe exactly what's going on. The users of the library will have no doubt about the function of your methods, neither the maintanance programmers.

You could also apply some design pattern here if you are really worried about exposing a large number of factory methods - like having factory methods with property classes. You could have a CircleProperties class with properties like CenterX, CenterY, Radius, (bool)UseCenterX, (bool)UseCenterY etc and then you pass this to the public factory method which will figure out which (private) factory method to use.

Assuming C#:

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

var circle = Circle.Create(circleProperties);
一场信仰旅途 2024-07-21 14:51:57

我的第一直觉是拥有更多类型,这将允许更直观的方法重载。

// 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 之外,您还可以定义 Distance(这将允许使用不同的单位)

如果这种风格适合您,请考虑为什么需要工厂方法而不是构造函数。

Circle c = new Circle(new Point(cx,xy), r);

My first instinct is to have more types, which would allow for more intuitive method overloading.

// 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);

As well as Point, you could define Distance (which would allow for different units)

If this style suits you, consider why you need a factory method instead of a constructor.

Circle c = new Circle(new Point(cx,xy), r);
川水往事 2024-07-21 14:51:57

对于不支持命名参数的语言,将方法名称设置为非常简单的名称(例如 Circle.create),然后仅添加额外的输入标志字符串(例如“center”或“bounding”)会更干净吗? ”)表明对于仅根据输入变量数量和类型难以区分的情况应如何解释输入值? 这样做的缺点是,它需要方法内部的额外逻辑来处理不同类型的输入参数,并且还要求用户记住标志选项。

For languages that don't support named parameters, would it be cleaner to make the method name something very simple like Circle.create and then just add an additional input flag string (like "center" or "bounding") that indicated how the input values should be interpreted for cases that are hard to discriminate based only on input variable number and type? Drawbacks to this would be that it requires extra logic inside of the method to handle different types of input arguments and also requires that the user remember the flag options.

淡墨 2024-07-21 14:51:57

我将拥有方法 CreateTriangle 并让重载显示所需的不同信息。

例如

Circle.CreateCircle(cx, cy, r)
Circle.CreateCircle(point1, point2)
Circle.CreateCircle(point, width, height)

I would have methods CreateTriangle and have the overloads show the different pieces of information required.

E.g.

Circle.CreateCircle(cx, cy, r)
Circle.CreateCircle(point1, point2)
Circle.CreateCircle(point, width, height)
ˇ宁静的妩媚 2024-07-21 14:51:57

是的,这更像是一个元答案,但我建议您看看 苹果的可可

Yes, this is more of a meta-answer, but I suggest you take a peek at how naming is done in Apple's Cocoa.

南渊 2024-07-21 14:51:57

你的直觉是正确的——以这种方式创造事物的整个模式是不确定的。

除非这些只使用一两次,否则它们会变得非常混乱。 如果您要创建一个包含 5 个圆形和 3 个三角形的形状,那将会很混乱。

除了简单示例之外的任何事情都可能最好通过某种数据驱动的实现来完成。

为了实现这些目的,使用字符串、散列或 XML 来定义形状可能非常有用。

但这完全取决于您期望如何使用它们。

我在 Java 中创建 Swing 控件时也遇到同样的问题。 您最终会得到一行又一行的“new Button()”,后面跟着一堆 .set 属性调用以及一行将值复制到对象(或添加侦听器)的代码,以及一行重置值..

这种样板文件永远不应该在代码中发生,因此我通常尝试找到一种用数据驱动它的方法,将控件动态绑定到对象 - 为此,基于描述性字符串的语言将非常有帮助。

Your instinct is correct--the entire pattern of creating things this way is--iffy.

Unless these are used just once or twice, they are going to become pretty messy. If you were creating a shape with 5 circles and 3 triangles, it would be a mess.

Anything beyond a trivial example would probably be best done with some kind of data-driven implementation.

Towards those ends, having it take a string, hash or XML to define your shapes might be extremely useful.

But it all depends on how you expect them to be used.

I have the same kind of issues with creating Swing controls in Java. You end up with line after line of "new Button()" followed by a bunch of .set property calls as well as a line of code to copy the value to an object (or add a listener), and a line to reset the value..

That kind of boilerplate should never happen in code, so I usually try to find a way to drive it with data, binding the controls to objects dynamically--and towards that end, a descriptive string-based language would be very helpful.

蒗幽 2024-07-21 14:51:57

我知道我知道。 对于 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)

这可能看起来非常陌生,但说实话:哪个版本更容易阅读?

I know, I know. This sounds completely crazy for you C/C++/Java people, but the examples given in the question and in all those answers clearly demonstrate what a bad, bad convention CamelCaseNaming really is.

Let's take another look at the original example:

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

And now let's get rid of that camel case notation

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)

This may seem terribly unfamilar, but be honest: which version is easier to read?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文