Hacker News new | past | comments | ask | show | jobs | submit login
Good Code Design from Linux (leandromoreira.com.br)
154 points by dreampeppers99 50 days ago | hide | past | web | favorite | 28 comments

Doesn't seem like the author knows C. The C example of codecs is riddled with syntax errors. When he writes

    struct Codec
        *int (*encode)(*int);
        *int (*decode)(*int);
he probably meant to swap the int and the asterisk to mean a pointer to int. But no one would use a pointer to int to mean bytes; we have pointer to char or pointer to unsigned char for that:

    struct Codec {
        uint8_t* (*encode)(uint8_t*);
        uint8_t* (*decode)(uint8_t*);
And that doesn't exactly deal with ownership issues.

But besides those nitpicking, I struggle to see what his point is. His point is to extract common features of components and build interfaces for them? I mean isn't that something we've been doing for a long time?

I think the author has not yet encountered C++ vtables, they should take a read of https://en.m.wikipedia.org/wiki/Virtual_method_table

The use cases are basically static, final methods in OO-speak. The article simply shows a straight forward way how to implement that.

I feel that he may be a Go programmer.

> But no one would use a pointer to int to mean bytes; we have pointer to char or pointer to unsigned char for that

Or just use void*, then the caller doesn't have to cast when they want to pass arbitrary data.

It's not like Linux invented the VFS either --- that was already there in the early Unices from which Linux got its inspiration.

"Everything is a file" concept, comes from Plan 9

It comes from unix. Plan9 applyed it further.

And then there was Inferno

He’s probably been doing a lot of go. I always struggle with this when I’m switching between the two.

yes, maybe for you it's clear but perhaps for many other developers, it's not! I don't think he claimed something new, just that you can promote abstractions and use them regardless of the language.

we often, as developers, see something as useful or not only from our point of view, which is fair since you're reading and you want to learn more, but we can't forget that there are many developers out there being formed/mentored that might benefit from this kind of post.

Are you the author of this post? Your HN user name matches the poster, and the username in the URL in the author page of the site at https://leandromoreira.com.br/author/dreampeppers99/

In any case I just don't think the author has made the case in a very clear way. Unifying all the codecs in a codec library through an interface is something whose novelty is lesser than that of everything-is-a-file. It takes more ingenuity to consider objects like pipes and sockets as files, and I hope the author didn't really lump them together. I just hoped the author would cover more things about this design pattern and explain his thesis more clearly in an article with such a grandiose title.

Yes, I'm and I do agree with you with some of your arguments. The lack of details might be a problem for you but it can transform the post easier for someone fresh.

It's always hard to know whether you're going too deep or too shallow, what are the target people?! I'm afraid, in this case, I didn't put as many details as I planned because every time I read it, it started to become be too difficult for newcomers and my idea was to show to anyone this idea of "we should try to do good code design despite the language since it works for many giant projects such as Linux"

I appreciate the time you took to read it and for the issues pointed: clarity and cover more thins, I'll pay more attention to the future posts and I'm open to suggestions, thanks. Maybe I miss the balance and I should put more details/examples into it.

Seems like a beginner dev. It can be a nice experience to learn by teaching. Just a bit confusing for the readers.

I struggled a lot with the title for this post =/ (I crossed like 6 titles) but I also wanted something to call attention (not from lead/principal/kernel devs expectations) to the value of good code design, again naming is hard =)

Is the only takeaway that polymorphic design is good for extensibility? I mean, isn't that the whole point of polymorphism? But Linux's everything's a file design is great. Makes for a great user experience when you know all the knobs are under /sys on sysfs

I think the author is rediscovering OOP or something it's kind of uncanny

Ironically, recently I've seen some people rediscover OOP after being told OOP is absolute evil.

as someone who did some university teaching, students rediscover OOP on their own all the time

Are you sure they discover specific things that are only part of OOP, because I find a lot of people conflate OOP with good design. Thinking in components is not something OOP invented, people did that long before there was OOP.

It's a great way to learn though.

This article is making a case for standardized interfaces and the techniques two popular open source projects use to implement it in C. I always find it nice to read articles taking an explanatory look at open source projects, regardless of if it presents anything "novel" in the process.

A non-obvious place where this pattern also exists is React components in JavaScript. Components define an interface via props, but the consumer of the component is the one who provides the event handlers. It's an inversion of control in the same way that passing around function pointers to complete an interface is.

I was hoping this was going to be an analysis of design patterns used within the Linux kernel codebase itself, but the "everything is a file" concept is undoubtedly worth talking about.

There could have been more discussion of the tradeoffs involved, though. The "file" abstraction doesn't seem to handle every kind of use case equally well.

He hints at it when he shows the file_operations struct.

Basically the way to achieve runtime polymorphism is to have function pointers in a struct.

But you don't necessarily put the pointers in the per-instance struct. That would take memory proportional to the number of instances. So you create something like file_operations, which is nothing but pointers and no instance data. Maybe the ext4 driver declares exactly one of them as static const. And so every ext4 file gets the same function pointers. Another filesystem is free to provide their own. This arrangement is pretty similar to C++ vtables.

Also note that some of the operations aren't unique to the filesystem. So ext4 points some function pointers at a generic implementation rather than a specific one.

So these are some of the patterns discussed. I think it is just not exceptionally clear writing. (And I saw one spot where they got the syntax for pointers incorrect...)

This is the first time I see the C language referred as Clang. Yes, I know LLVM.

Consider the following:

* one slot for a variadic function pointer

* another slot for a datum that fully describes the function signature for the function the first slot points to.

This allows the programmer to specify whatever types the interface allows in parameters of the function callback. Otherwise the programmer must use a catchall interface like "argc, argv" and then add steps inside the function body to fetch the args. At least in my experience programmers screw up way more often with the catchall interface than they do with typing the correct function parameters.

There's just one "tiny" problem with this approach. :)

Nevertheless I've seen this technique in old code that still runs on every modern architecture on which someone bothered to compile it. Gcc doesn't complain about the tiny problem unless you use emscripten to compile to web assembly. (And even there you can still get away with undefined behavior as long as the number of parameters agree.)

This is a very simple principle, yet I see it constantly violated in big projects with plenty of redources. Even though it seems obvious, it takes a lot of effort and arguing to keep these kind of interfaces small and effective.

wait until you discover java's interfaces

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact