Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling Singular and Plural Controllers/Routes

I'm a little confused on how I should handle singular and plural routes and controllers in my web application.

The website is a simple quotes site - think Einstein, Shakespeare etc. not Insurance. Within the project I have a controller called `QuoteController'. The controller name is singular, so does this mean that the controller should only handle the display of single quotes? I.E.

/quote/love-is-a-battlefield-1 

Do I then need another controller for the display of multiple quotes (plural)? For example:

/quotes/ (would default to most recent) /quotes/new /quotes/shakespeare /quotes/popular 

Is it convention, or good practice, to have separate controllers for singular and plural routes? I hope that makes sense.

like image 873
James Jeffery Avatar asked Sep 02 '13 09:09

James Jeffery


People also ask

Should routes be plural or singular?

Routes are generally defined as plural using the plural resources . Singular routes* are a little different – they are written as singular resource .

Should controller be plural or singular?

A controller is plural because it is the controls (methods) for the collection of Users.

What is a route controller?

The Route Controller is responsible for the preparation of the daily Delivery plan, monitoring the progress of Deliveries,Communicating the Route revisions to the Customer as well as the events that will have an impact on the Customers delivery.

What is controller in Nodejs?

In addition to the views and routes the diagram shows "controllers" — functions that separate out the code to route requests from the code that actually processes requests.


2 Answers

Just because the default controllers of asp-mvc have singular names, it doesn't mean you should implement singular form for all your controllers.

The correct answer is: it depends on the quantity of the entity that your controller represents.

Singular, example the AccountController is singular because it represents actions (action method) pertaining to a single account only.

Plural If your controller contains at least one action method that handles multiple entities at a single transaction.

Example plural format

users/update/3 

The route above makes you think you are editing all users, which does not makes sense if you read it like a sentence. However, if you read your route like query, it will make much more sense.

If we think about it, a route IS a query: {entities}/{action}/{parameter} looks like a query to me.

users/ shorthand of users/all reads "select all users table"

users/123 reads "select single entity from users table"

users/update/123 reads "update single entity from users table"

Major sites use plural format, see sample below

stackoverflow.com/questions          <- list of questions   (multiple) stackoverflow.com/questions/18570158 <- individual question (single) stackoverflow.com/questions/ask      <- new question        (single)  stackoverflow.com/users        <- display list of users (multple) stackoverflow.com/users/114403 <- individual user       (single)  asp.net/mvc/tutorials        <- display list of tutorials (multiple)  asp.net/mvc/tutorials/mvc-5  <- individual tutorial       (single)  facebook.com/messages/     <- Display list of messages (multiple) facebook.com/messages/new  <- Create a single message  (single) facebook.com/messages/john <- view individual messages (multiple) 

I believe that English grammar should be strictly incorporated in every programming aspect. It reads more natural, and leads to good code hygiene.

like image 81
Yorro Avatar answered Sep 19 '22 07:09

Yorro


Answer

Here's a question asked in programmers StackExchange that suggests keeping class names singular. I especially like the logic in one of the answers, "The tool to turn screws with is called "screw driver" not "screws driver"." Which I agree with. The names should be kept to nouns and adjectives.

As far as routing goes, best practices seems to favor that routes be pluralized nouns, and to avoid using verbs. This Apigee blog says, "avoid a mixed model in which you use singular for some resources, plural for others. Being consistent allows developers to predict and guess the method calls as they learn to work with your API." and suggests using singular or plural based off what popular websites have done. Their only example for using singular nouns in the route is the Zappos site, which has http://www.zappos.com/Product as a route; but if you examine the site, it's not exactly a route to a product resource but is instead a query, probably for all their products. You can enter http://www.zappos.com/anything and get a results page. So I wouldn't put too much stock into that.

Other blogs like this one from mwaysolutions (random find) say to "use nouns but no verbs" and "use plural nouns". Other points aside, most blogs/articles tend to say the same thing. Plural nouns and no verbs.

TL;DR: Use singular nouns for controllers and plural nouns for routes.

Controllers

Controllers and routes represent two different concepts. The controller is a class, or a blueprint. Similar to a stamper, I wouldn't say I had a UnicornsStamper I'd say I had a UnicornStamper that makes a stamp of a unicorn with which I could make a collection of unicorn stamps with. Collections, Enum types that are bit fields, static class that is a collection of properties (acts like a collection), and probably a few other edge cases are where I'd use a plural name.

Routes

A(n) URL is an address to a resource, thus the name Uniform Resource Locator. I disagree that "a route IS a query". Routes can contain queries (query string) to narrow down returned resources but the route is the location or the resource(s) that's being requested.

With the advent of attribute routing, pluralizing routes for controllers is as easy as adding a [RoutePrefix("quotes")] attribute to the QuoteController declaration. This also allows for easier design for associative routes. Looking at the sample routes provided in the original question:

/quotes GET: Gets all quotes POST: Creates a new quote /authors/shakespeare/quotes Associative route in the QuoteController GET: Gets all Shakespeare quotes /quotes/new This is a bad route IMO. Avoid verbs. Make a POST request to '/api/quotes' to create a new quote /quotes/shakespeare /quotes/popular Although these would be nice to have, they're not practical for routing (see below)

The problem with the last two routes is that you have no simple way of differentiating between popular quotes and quotes by authors, not to mention that routes that link to quotes by name or Id. You would need actions decorated with [Route("popular")] followed by [Route("{author}")] (in that order) in order for the routing table to pick the routes up in the appropriate order. But the author route kills the possibility of having routes [Route("{quoteName}")] or [Route("{quoteId}")] (assuming quoteId is a string). Naturally, you'll want to have the ability to route to quotes by name and/or ID.

Slightly Off Topic

Getting quotes by author would best be done by an associative route. You could still probably get away with the popular route as a static route name, but at this point you're increasing route complexity which would be better suited for a query string. Off the top of my head, this is how I might design these routes if I really wanted to have the popular search term in the route:

a:/authors/{authorName}/quotes b:/authors/{authorName}/quotes/popular c:/authors/{authorName}/quotes?popular=true d:/quotes/popular e:/quotes/popular?author={authorName} f:/quotes?author={authorName}&popular=true g:/quotes/{quoteName|quoteId}

These could be spread across the QuoteController's actions. Assuming the controller has a [RoutePrefix("quotes")] attribute:

[HttpGet] [Route("popular")] [Route("~/authors/{authorName}/quotes/popular")] // Handles routes b, d, & e public ViewResult GetPopularQuotes(string authorName) return GetQuotes(authorName, true); [HttpGet] [Route("")] [Route("~/authors/{authorName}/quotes") // Handles routes a, c, & f public ViewResult GetQuotes(string authorName, bool popular = false) // TODO: Write logic to get quotes filtered by authorName (if provided) // If popular flag, only include popular quotes [HttpGet] [Route("{quoteId}")] // Handles route g public ViewResult GetQuoteById(string quoteId) // TODO: Write logic to get a single quote by ID

Disclaimer: I wrote these attributes off the top of my head, there may be minor discrepancies that would need to be ironed out, but hopefully the gist how to get these routes to work comes through.

Hopefully this helps to clear up some confusion on the topic of controller and routing best practices on naming conventions. Ultimately the decision to use plural or singular controllers or routes is up to the developer. Regardless, be consistent once you pick a best practice to follow.

like image 37
nwayve Avatar answered Sep 21 '22 07:09

nwayve