
Good Code Design from Linux - dreampeppers99
https://leandromoreira.com.br/2019/08/02/linux-ffmpeg-source-internals-a-good-software-design/
======
kccqzy
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?

~~~
joosters
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](https://en.m.wikipedia.org/wiki/Virtual_method_table)

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

------
aloknnikhil
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

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

~~~
jcelerier
as someone who did some university teaching, students rediscover OOP on their
own _all the time_

~~~
smnplk
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.

------
CGamesPlay
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.

------
decasia
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.

~~~
asveikau
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...)

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

------
jancsika
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.)

------
oracle2025
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.

------
_ZeD_
wait until you discover java's interfaces

