All the streams in core are in some half state between declarative and composable.
http.ServerResponse is probably the biggest/worst example where: http.writeHead(status, headers) can, in some cases, entirely opt out of the composable headers set: http.setHeader(name, value) in particular, this happens when you pass an array of tuples as the headers argument to writeHead. Then there is http.ClientRequest, which is not composable at all and has no setHeader() method. I have a similar problem with every stream in core except sockets. All of the streams in core take, at some point, a set of parameters that set a bunch of internal state and *start* an IO operation. Until that IO operation hits a particular event, in the future, none of that internal state is actually used. Some of that state can be mutated (is composable), some currently isn't (is not composable), and some of it is mutable if you access internal properties (ewwww). If the goal of core is to reach API stability we need to get core to a place where it's extensible. There is a similar thread to this effect about exposing core constructors, but I'd like to stay on track in this thread and just talk about composability because it doesn't have many of the same concerns people have about exposing core constructors. *Most* of the objects in core are accessed by userland as the subject of an event. When those objects are not composable we incredibly limit the extensibility of core, even when we expose the constructors, and it leads to the worst kind of monkey patching. There are even cases where core objects that get exposed by libraries have certain methods entirely removed because they break composability (I know TJ was considering removing writeHead when exposed by Express). A few things would need to happen to make core more composable. 1) Internal state needs to become external state. and 2) The removal, or "re-integration", of methods that currently break composability. We may also need to add more events to some objects. Some good examples, which have been added, are the 'open' and 'socket' methods on fs.ReadStream/fs.WriteStream and http.ServerResponse. Anywhere we can expose internal state publicly we increase composability because we allow new mutations that depend on that state the way internal logic depends on it. As we do this we'll also realize more places where we break that mutability. Thoughts?
