Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Are there any guidelines for placing methods in API when the placement isn't obvious?

Example: I have classes A and B and a method X. The work being carried out can be phrased in two ways:

  1. A does X with B
  2. B does X to A

Given the two ways of phrasing this, it's unclear whether X belongs in A or B. Are there guidelines for placing the method in this scenario?


For a more concrete example, consider think of a user (A), an event (B) and a sign-up action (X). A user can sign up to an event (A does X with B ), or an event can add a user to the sign-up list (B does X to A).

share|improve this question

3 Answers 3

up vote 3 down vote accepted

Are there any guidelines for placing methods in API when the placement isn't obvious?

For case like that, I would suggest a "guideline" to redesign API so that placement becomes obvious.

  • Think of users of your API: if it isn't obvious for you, the designer, it will likely be heavily obscure to API users who haven't the luxury to read your mind.

    "Public APIs, like diamonds, are forever. You have one chance to get it right so give it your best..." (Joshua Bloch, How to Design a Good API and Why it Matters)


For your example with user who can sign up to an event and an event that can add a user to the sign-up list, I would give a serious consideration to establishing a third class like SignupAction.

To me, the primary purpose of this "third" class would be to resolve ambiguity so that developers using your API wouldn't need to break their mind where to look for it (in users? in events?). This is the starting point, from which you can proceed wherever requirements drive you - by adding methods, states, additional classes etc.

share|improve this answer
    
I take it that the purpose of the third, class would be to provide that single operation, and maybe some inverse operation too? –  AndyBursh Mar 4 '12 at 16:52
    
@AndyBursh I expanded answer to cover more details on the purpose –  gnat Mar 4 '12 at 17:13
    
Fantastic, thankyou –  AndyBursh Mar 4 '12 at 17:16

The three class approach is tempting because it mirrors correct database design, mapping one class to one table. It's very elegant from a high-level conceptual design, but is usually overly complex in an actual implementation, and therefore rarely used in popular APIs. Usually relationships are described by both of the involved objects, as in facebook's event and user APIs.

For example, look at GUI toolkits with containers full of widgets. You call container.add(widget), which internally calls something like widget.setContainer(container). Once the container-widget relationship is established, sometimes you call container.getWidgets(), and sometimes you call widget.getContainer().

Now consider how this would be implemented with a third, ContainerWidget object. Every time you wanted to create an association, it would look like this:

containerWidget = new ContainerWidget(container, widget);
container.addContainerWidget(containerWidget);
widget.setContainerWidget(containerWidget);

To get a widget's container would look like this:

widget.getContainerWidget().getContainer();

Eventually someone's going to get annoyed with typing that, and just create a widget.getContainer().

Getting all the widgets for a container is even more complicated:

containerWidgets = container.getContainerWidgets();
for (containerWidget in containerWidgets)
    widgets.append(containerWidget.getWidget());

Eventually someone's going to get annoyed with that, and create a container.getWidgets(). Then eventually someone will notice that since we already have those methods anyway, and rather than rebuild the list every time it's called, it would be a lot easier just to store a list of widgets in the container and a pointer to the container in the widget.

See where I'm going with this? Either you end up with unnecessary complexity, or you eventually simplify down to the two class solution.

The exception to the rule is when you need to describe attributes of the relationship itself. For example, a spousal relationship between two people doesn't merit a third class. You just put a Person pointer in the Person class to point to the current spouse. However, a marriage relationship merits a third class, because marriages have places, start dates, end dates, etc. that describe aspects of the relationship other than the mere fact it exists.

share|improve this answer

To start with, an API shouldn't be grouped by class type.

If you are creating a controller/handler to organize events, you should have an OrganizeEvents controller/handler that would expose the methods like ListAllEvents(), AddPersonToEven() etc.

Generally you should group API functions by theme and purpose, instead of classes. Then, you can use the classes you need to provide the correct output each time.

Defining relations on your backend shouldn't be too hard, and normally it would involve reflecting a database pattern with a linking table.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.