On Wednesday, 11 December 2013 at 08:21:33 UTC, luka8088 wrote:
Hi everyone!

I would like to address the issue of global variables (or states). In general my opinion is that they are bad solely because they (in most cases) lack the ability of alternative values (or states) or ability to
alter them in user friendly way.

For example, take write function from std.stdio. For a third party function that uses write to output to screen user is unable to redirect
that output to, for example, file without altering third party
function's body. Or if there is a way it rarely user friendly. For example, in php there are function for buffering output but you have to manually start buffering and manually stop it. In python active output is a global variable and you are able to replace it with a custom file stream but you are responsible maintain a custom stack in case of recursion and switching it back to default output when no longer needed.
There are also examples of loggers, database connections, etc.

I have a proposal to generalize this issue. Attached is a example library that implements context based approach and I would like to see this kind of library in phobos (std.context). It is very simple and yet
in my experience it has shown to be very useful.

Examples using such library:

void writeOutput () {
  writeln("example output");
}

void main () {

  writeOutput();

  standardOutputContext(file("example.txt"), {
    writeOutput();
  });

}

MVC example:

void databaseToView () {
  auto result = db.query("select;");
  view.populate(result);
}

void myAction () {

  auto customView = new View();

  viewContext(customView, {
    databaseToView();
  });

  view.regionA.append(customView);

}

void main () {

  dbContext(defaultDbConnection {
    viewContext(defaultView, {
      myAction();
    });
  });

}


I would like to add this to phobos and document it but I would like to know if this is desirable at all and to get a community feedback.

Thoughts?

This issue is probably nearly as old as programming itself.
There are several sollutions already developed: dependency injection (requires complex configuration rules), manually passing deps as args (cumbersome), service locator or global variables.

Your sollution as far as I understand it relies on swapping a global variable when inside a context and restoring it afterwards. While this would be perfectly fine in environment where code is executed in OS threads, there will be a problem in the case of Vibe.d which uses fibers. But I guess the problem is solvable there aswell.

Just to note - you have to bind to globals at some point - what if someone wants to swap writeln function whith his own (for example to call logger, or for whatever reason)? Or he may want to swap dbContext :).In my practice I make swappable only things I think I'll need to swap in future.

Reply via email to