54

Sounds pretty basic, I know, but I recently had a colleague tell me that a method called startHttpServer is too complicated to understand because it only starts the server if it's not already running. I find I get into trouble when I respond with, "Seriously? I've been doing this for decades - it's a common pattern in programming." More often than I care to admit he comes back with some documented evidence that shows that the entire programming community is behind his point of view and I end up feeling sheepish.

Question: Is there a documented design pattern behind the concept of a method that is a no-op if the action required is already in effect? Or, if not a pattern, does it have a name either? And if not, is there any reason to think it's too complicated to consider writing a method in this manner?

Doc Brown
  • 218,378

8 Answers8

128

As NickWilliams has already said: the concept the OP describes is called idempotent (noun Idempotency). It is indeed common practice, especially in high-level APIs.

BUT: Rename the function.

Instead of startHttpServer call it makeSureHttpServerIsRunning or ensureHttpServerIsRunning.

When a function is called startHttpServer, readers expect it to start a HTTP server; when called ten times in a row, I'll have ten servers running. Your function doesn't do that most of the time. Additionally, the name with "start" suggests that if I want only one server running I'll have to keep track of whether the function has already been called or not.

When a function is called makeSureHttpServerIsRunning, I assume it will do the necessary things to make sure that a HTTP server is running, most likely by checking if it is already running, and starting it otherwise. I also assume that the function makes sure the server is actually running (starting a server might involve some time where it is not quite running yet).

gnasher729
  • 49,096
33

Rename it to EnsureServerRunning.

Completely unambiguous and is clear that it makes sure it is running (if it isn't) without implying a restart if it is.

(Alternative: StartServerIfNotRunning?)

Stilez
  • 507
30

Not really a design pattern but I would call your method idempotent. There term is usually used to refer to remote calls but the description seems the match what you are doing.

Idempotent Methods. Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. (From W3.org)

The server side effect here being that the http server is started once the method is called. I see nothing wrong with a method doing this.

If you need a design pattern I guess you could expose your httpServer as a singleton which is started when initialized.

7

As the one who implement this tool, startHttpServer, you should be trying to make it the most simple, smooth and seamless to use...

The function's logic

Technically, by splitting startHttpServer's logic into 2 functions and calling them separately, all what you do is moving startHttpServer's idempotency into the code calling both functions instead... Furthermore, unless you wrap both logic in a third function (which is what does startHttpServer in first place), this forces you to write unDRYed code, duplicating it exponentially everywhere you'd have to call startHttpServer. In short, startHttpServer has to call itself the isHttpServerRunning function.

So my point is:

  • Implement isHttpServerRunning function because this may be needed independently anyway...
  • Implement startHttpServer making it use isHttpServerRunning to define its next action accordingly...

Still, you can make startHttpServer return any value the user of this function may need, eg:

  • 0 => server starting failure
  • 1 => server starting success
  • 2 => server was started already

The function's naming

First of all, what is the primary goal of the user? To start HTTP server, right?

Fundamentally, there is no problem by intending to start something that have been started already, AKA 1*1=1. So, at least to me, calling it "ensureHttpServerIsRunning" seems not critically needed, I'd care more about how long, natural and memorable the function's name is.

Now if you want to know how work in detail the function under the hood, there is the documentation or code source for that, I mean like for any other function from library/framework/API/etc...

You learn the function once while you write it multiple times...

So anyway, I'd stick with startHttpServer which is shorter, simpler and more explicit than ensureHttpServerIsRunning.

ClemC
  • 401
2

I suppose that your colleague meant that startHttpServer is doing too much:

  • Checking whether the server is already running,
  • Starting the server if needed.

Those are two unrelated parts of code. For instance, a similar situation exists when a desktop application should ensure that it's not already running when launched; there will be a part of code which handles app instances (for instance using a mutex), and the code which will start the application message loop.

This means that you have to have not one, but at least¹ two methods:

  • isHttpServerRunning: boolean
  • startHttpServer

The application entry point will call the first method, and then the second one if the return value is false. Now, every method is doing one and one thing, and is easy to understand.


¹ If the logic needed to know if the server is already running is too complex, it may require further separation into multiple methods.

2

Since you don't specify a language, in JavaScript many libraries have a "once" function e.g. Underscore. So, if that would be familiar to you, call it a "once" pattern and possibly rename your method.

Myself, coming more from Java, the terms "caching" or "lazy evaluation" come to mind. "Idempotent" is technically correct and a good choice, esp. if you have a more functional background.

user949300
  • 9,009
-2

I'd prefer startHttpServerIfNotIsRunning.

This way, the condition is clearly mentioned already in the method name. Ensure or makeSure seems a bit vague to me, as it is not a technical expression. It sound like we don't know exactly what's going to happen.

Herr Derb
  • 439
-3

What your colleague should have told you is that you have no business writing that method. It's already been written plenty of times, and written better than you're likely to write it. For example: http://docs.ansible.com/ansible/latest/systemd_module.html https://docs.saltstack.com/en/latest/ref/states/all/salt.states.service.html

From an architectural perspective, having some arbitrary bit of code managing a web server is the stuff of nightmares. Unless managing services is exclusively what your code does. But I'm guessing you didn't write monit (or kubernetes or ...).

Andrew
  • 95