
Ask HN: In general, prefer your abstractions vs. runtime ones ASAP? - kizer
I’ve been working on an http server in C as a side project, and while studying the code bases of other C projects, I’ve noticed that there is a tendency to start programming in terms of the project’s own abstractions (structs, functions) at the lowest levels, or “as soon a possible”; e.g., to use a custom file descriptor structs, custom versions of read(2) and write(2) or equivalent “enhanced” functions. What I mean is that I see for example the native FILE or bind&#x2F;listen&#x2F;accept once, but then  they are either always wrapped or remain encapsulated at a lowest implementation layer.<p>The way I see it, this effectively maximizes the proportion of your code that speaks in your own abstractions, which certainly makes coding easier (working in your vernacular, so to speak).<p>Is this intentional, and is there a principle or pattern being applied? For reference, I’ve been looking at ngnix, libuv, livevent, redis and SQLite, the latter two a while back so they may not follow my description.
======
Someone
I suspect that, if you read those “custom versions of read(2) and write(2)”,
you’ll discover that those APIs “leave something to be desired”.

For example, let’s say you want to write a 100 byte struct to file, and
_write_ returns 0 and sets _errno_ to _EINTR_ , or return 67 and keep _errno_
as is.

Why would you write the code to handle those cases in every function that
writes data? How would you fix all those entry points if you discover your
handling is buggy, or that some commonly used file system is buggy, and you
need to implement a workaround?

Similarly, if you _read_ those 100 bytes, your call may return 67 and update
the file position. You need code to recover from that. Why duplicate that
throughout your code?

------
billconan
I'm working on a c++ webserver too.

I don't want to over engineer it, so I don't write a wrapper for file
descriptor.

I studied lwan, for inspiration. I too see it has some abstraction layers. I
think it is mainly for cross-compiling on different platforms, it needs to
abstract the socket, event, io APIs.

My project is linux only. So I want to stay simple.

