Live data from Hacker News

Object-oriented design patterns in C and kernel development

oshub.org

151–160 of 224 posts

Re: Object-oriented design patterns in C and kernel development

#151
Never. Do. This...

I was involved in a product with a large codebase structured like this and it was a maintainability nightmare with no upsides. Multiple attempts were made to move away from this to no avail.

Consider that the code has terrible readability due to no syntax-sugar, the compiler cannot see through the pointers to optimise anything, tooling has no clue what to do with it. On top of that, the syntax is odd and requires any newbies to effectively understand how a c++ compiler works under-the-hood to get anything out of it.

On top of those points, the dubious benefits of OOP make doing this a quick way to kill long-term maintainability of your project.

For the devs who come after you, dont try to turn C into a poor-mans C++. If you really want to, please just use C++.

Re: Object-oriented design patterns in C and kernel development

#152
post #130

Earlier quoted context omitted.

What guarantee do you have that ->ops is a vtable? It could contain function pointers that don’t take an implicit this argument like struct file_operations in Linux does. It could also contain variables that are non-pointers. Neither is allowed in a vtable, but both are fine to do in C.

As it isn't the compiler that creates the vtable, you can also have the equivalent of this as the last parameter or where you want it to be. > It could also contain variables that are non-pointers. The convention of it being a pure vtable is that it just doesn't. > Neither is allowed in a vtable Who is the vtable membership authority? :-)

You can take the API for a linked list and implement a balanced binary search tree behind it, but continuing to call it a linked list after doing that is wrong. Similarly, you can do pointer indirections the same way a vtable would do them, but if the things you get are not the equivalent of member function pointers, it is not a vtable.

Re: Object-oriented design patterns in C and kernel development

#153
post #125

Earlier quoted context omitted.

vtables contain function pointers to functions that take “this” pointers. The author mentions struct file_operations as an example of a vtable. struct file_operations contains a pointer to a function that does not take “this” pointer. It is not even a vtable.

I would still call it a vtable. Who assures you that every function of a class needs a pointer to the object instance? When you don't need it, you can just leave it of when you roll your own.

Static member functions are tied to the class while virtual member functions are tied to the object. If you throw the static member functions into a vtable, you will at best have a bug where the static member function from a different class can be called. Alternatively, you would have an undefined behavior where the other class in the hierarchy does not implement this function.

There is a saying “If Your Only Tool Is a Hammer Then Every Problem Looks Like a Nail”. That is precisely what is happening here with the insistence to call what appears to be all structures of function pointers vtables. A vtable is something that follows a fairly well defined pattern for implementing inheritance. Not all things containing function pointers are vtables.

Re: Object-oriented design patterns in C and kernel development

#154
post #131

Earlier quoted context omitted.

You were not discussing the article in your previous reply. That said, I have repeated explained why both you and the author article are wrong to describe that structure of function pointers as a vtable by giving examples of it containing things that are not allowed in vtables (if say a C++ compiler did this to its vtables, it could cause the wrong function to be called when trying to call a static member function).…

The term "vtable" is not exclusive to C++. Trait function dictionaries in Rust are called vtables and behave as described here, there's not necessarily any 'this' or 'self' object.

The point of the vtable is to allow dynamic dispatch based on the actual type of an object. When you have a function that does not need a this pointer, it no longer depends on the type of the object and putting it in there anyway could cause you to execute a variant depending on the type of the object, which seems like a buggy undesirable behavior.

Re: Object-oriented design patterns in C and kernel development

#155
post #6
post #2

> The article describes how the Linux kernel, despite being written in C, embraces object-oriented principles by using function pointers in structures to achieve polymorphism. This technique predates object oriented programming. It is called an abstract data type or data abstraction. A key difference between data abstraction and object oriented programming is that you can leave functions unimplemented in your abstrac…

In Smalltalk and Objective-C, you just check at runtime whether an object instance responds to a message. This is the original OOP way. It's sad that OOP was corrupted by the excessively class-centric C++ and Java design patterns.

This is a very good point. A greater distinction needs to be made about class-based versus class-free OOP. Many of the problems or constraints around OOP that people don't like, come back to classes.

Often class-based programming is confused as being the only style of OOP, superior to all other styles, or heavy-handedly pushed on others. Many programmers are perfectly fine with using objects or only specific features of OOP, without classes, if they are "allowed" to.

Re: Object-oriented design patterns in C and kernel development

#156
post #133

Earlier quoted context omitted.

The curiosity of learning is infeasible given that there are >15,000 programming languages. You might say to only learn the major/influential languages, but I have found my curiosity to wane with every additional language that I learn. So far, I have either used or dabbled in C, C++, FORTRAN, SML/NJ, PHP, Java, JavaScript, Python, Go, POSIX Shell, Assembly and SQL stored procedures. That is not to mention different d…

How do you got proficient in so many languages? I think it takes some years, before you start to think in a language.

My proficiency in them varies. I have used them for projects, such that I can write code in them (provided I have references to read), but when I do, I only learn/use the subset of the language that I need. If I want to read code others have written, then I need to know the subset that they used and that is not always the subset that I know. Most of them are languages that I have used for a handful of projects or in the case of assembly, for very small portions of projects, with at least half of that spend just trying to understand how good of a job the compiler did in critical loops.

There are some languages in which I am extremely proficient. My best language is C, which is my favorite and I have used most features of every version of C from C89 to C11. My second best is probably either C++ or POSIX shell (although I have moments where I forget certain syntax and need to look it up, especially in POSIX shell for variants on variable substitution, e.g. ${VAR%%foobar}). I have used most features of C++98 and some from newer versions. My experiences with C++ have soured me on it, so I now try to avoid C++ whenever I can in favor of C and Python.

My first language was actually PHP 4.2.y, and I was fairly proficient in it, having spent a long time learning it while simultaneously writing my own code for a website as a teenager. However, I never once touched the portions describing objects/classes, namespaces or exceptions. Someone else at work writes Modern PHP code using Symfony and I have taken a peek at it. It looks very different from the PHP I knew because it uses the features I had avoided learning (and probably some new language features too), although I can sort of read it thanks to having learned those concepts in other languages.

I used SML/NJ and Java in college. Years after college, I modified an open source Android TV application written in Java to add some things I wanted, although honestly, beyond that I have not really touched either language. Give me an arbitrary application written in either to improve and I would have some difficulty, although I will probably be able to do it after filling the gaps in my understanding (and doing plenty of head banging if it is a large program).

I have used JavaScript for a few recent projects via electron/nodejs and I have done several small things in Python over the past several years. Each time, I only worked with the subset that I need. I am far from a master of either language that can understand arbitrary code written in them, but I am able to manage as far as my specific needs are concerned.

I could continue listing my experiences doing things in languages (like the time in college that I wrote some basic programs in FORTRAN 90 to try to learn it), but they really are not that interesting. It was often a project here or a small application there, and as I readily admitted, I only used a subset of most of the languages. For programming, a subset of commonly used bits is often all you need.

Re: Object-oriented design patterns in C and kernel development

#157

Earlier quoted context omitted.

How do you got proficient in so many languages? I think it takes some years, before you start to think in a language.

I did not know they say the same thing about programming languages. Based on his comment, I did not think that he is proficient in them, but that he has used them, which is fair enough, so have I, sans all the ones tied to either Apple (Swift) or Microsoft (C#). I have some projects in Haskell just for curiosity's sake, and because what I wanted seemed like it would be nice in Haskell, and it indeed looks quite elega…

You are correct. I am only highly proficient in a few of them. The others are ones that I have used for varying sized projects for varying reasons, but I only learned the subsets I needed for my purposes. I would say my ability in the others in my main list varies within the low to intermediate range of proficiency.

Re: Object-oriented design patterns in C and kernel development

#158
post #157

Earlier quoted context omitted.

I did not know they say the same thing about programming languages. Based on his comment, I did not think that he is proficient in them, but that he has used them, which is fair enough, so have I, sans all the ones tied to either Apple (Swift) or Microsoft (C#). I have some projects in Haskell just for curiosity's sake, and because what I wanted seemed like it would be nice in Haskell, and it indeed looks quite elega…

You are correct. I am only highly proficient in a few of them. The others are ones that I have used for varying sized projects for varying reasons, but I only learned the subsets I needed for my purposes. I would say my ability in the others in my main list varies within the low to intermediate range of proficiency.

Yeah, same here. This Haskell project is nothing serious, it just prints you the difference in time between two dates. I thought the Haskell implementation would look nice and it did. I initially made it in bash but I realized this is much more complex than what bash can handle. I had to calculate for particular calendars among a lot of other things. I think it works, more or less, however.

Re: Object-oriented design patterns in C and kernel development

#159
Hi, I don't know much about this. But it seems to me that the OP is doing it differently than the kernel devs. If you read the article that the OP links, then you get the impression that the vtables contain typed function pointers, while OP uses void pointers. Also the main benefit mentioned in the kernel dev article is that you save memory, by not having multiple function pointers in each structure instance, but instead you have just one pointer to a vtable in each instance. Thus the main benefit is saving memory according to kernel dev, but OP uses this vtable as a form of indirection to implement runtime method swapping and polymorphism, which is not even mentioned in the kernel dev article. Thus, OP uses some other pattern than the one mentioned by kernel dev.

Re: Object-oriented design patterns in C and kernel development

#160

Earlier quoted context omitted.

that's not really true - unlike a regular pointer, `this` is not allowed to be null, thus removing `if(this == nullptr)` is always a valid optimization to do.

It absolutely is allowed to be null: #include struct Foo { void bar() { std::cout bar(); } will print 0

That code is outside the set of valid c++ programs
Post reply on HN