Live data from Hacker News

Object-oriented design patterns in C and kernel development

oshub.org

131–140 of 224 posts

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

#131
post #123
post #109

Earlier quoted context omitted.

It is not a vtable. It is a structure of function pointers called struct inode_operations. It is reused for all inodes in that filesystem. If you get it from one callback, you can safely use it on another struct inode on the same filesystem without a problem because of that, because nobody uses this like a vtable to implement an inheritance hierarchy. There are even functions in struct inode_operations that don’t eve…

Again, this just isn't responsive to my comments, which discuss the article. The article's author is clearly talking about OOP. You've invented some alternative article and are arguing about that instead; I'm not interested.

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). You ignore that.

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

#132
post #115
post #110

Earlier quoted context omitted.

I would call returning something being implemented as a stub rather than being unimplemented. When something is unimplemented and you try to call it, you crash due to a NULL/invalid pointer dereference, not get an error back. Of course, as far as getting things done is concerned, the two might as well be the same, but as far as how the language works, the two are different.

Crashing is optional, depending on error model of the language. C has pitiful error model, thus you'll usually end up jumping to 0... but I recall at least one C environment where that gave you an error back instead of crash. As far as OOP is concerned, lack of implementation is not an issue in instantiating something - an object will just not understand the message, possibly catastrophically.

I was referring to POSIX functions when talking about stubs versus unimplemented functions. Messaging in a programming language is a different animal; one that I have yet to fully understand. Objective C for example resolves messages to function calls, so they look like function calls to me. I would love to know how they differ, but I have never dug into it.

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

#133
post #8
post #6

Earlier quoted context omitted.

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.

Actually I would say that it is sad that developers learn a specific way how a technology is done in language XYZ and then use it as template everywhere else, what happened to the curiosity of learning?

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 dialects/versions of those, and the fact that assembly itself is a catch all category in which I have dabbled in multiple languages too. I am also not including languages for which I spent a minuscule amount of time (say a few hours), such as D (as in DTrace), Objective-C, Perl, COBOL and LISP. Then there is the misadventure into C# I took before I actually understood programming where I got stuck and dropped it. I am also not sure if I should mention AWK, as I only use it to select the Nth field in a bunch of lines of text when doing shell scripting and nothing else. Thus, I have used it many times, yet know almost none of its syntax.

Every few years, someone tells me I should learn another language, and in recent years, there just is no desire in my mind to want to learn yet another language that is merely another way of doing something that I already can do elsewhere and the only way I will is if I am forced (that is how I used Go).

That said, I do see what you are saying. C++ for example has an “support every paradigm” philosophy, so whenever someone who has learned C++ encounters a language using a paradigm that C++ assimilated, there is a huge temptation to try to view it through the lens of C++. I also can see the other side too: “C++ took me forever to learn. Why go through that again when I can use C++ as a shortcut to understand something else?”. C++ is essentially the Borg of programming languages.

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

#134
post #131
post #123

Earlier quoted context omitted.

Again, this just isn't responsive to my comments, which discuss the article. The article's author is clearly talking about OOP. You've invented some alternative article and are arguing about that instead; I'm not interested.

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.

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

#135
post #87

Earlier quoted context omitted.

OOP does not disallow instantiation with unimplemented functions, it's just an artefact of implementation in some languages.

OOP only disallows inheritance with unimplemented functions when it's a contract violation. So that is to say, if the base class has a certain function which must be implemented and must provide certain behaviors, then the derived class must implement that function and provide all those behaviors. The POSIX functions like read and write do not have a contract which says that all implementations of them must successfu…

That sounds like a case of the Liskov substitution principle.

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

#136
post #110

Earlier quoted context omitted.

OOP only disallows inheritance with unimplemented functions when it's a contract violation. So that is to say, if the base class has a certain function which must be implemented and must provide certain behaviors, then the derived class must implement that function and provide all those behaviors. The POSIX functions like read and write do not have a contract which says that all implementations of them must successfu…

I would call returning something being implemented as a stub rather than being unimplemented. When something is unimplemented and you try to call it, you crash due to a NULL/invalid pointer dereference, not get an error back. Of course, as far as getting things done is concerned, the two might as well be the same, but as far as how the language works, the two are different.

Having a stub or having a NULL pointer are two ways to leave something unimplemented. Which you use is an implementation detail. You can also use some other sigil instead of NULL.

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

#137
post #133
post #8

Earlier quoted context omitted.

Actually I would say that it is sad that developers learn a specific way how a technology is done in language XYZ and then use it as template everywhere else, what happened to the curiosity of learning?

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.

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

#138
post #121

Earlier quoted context omitted.

Here's one example. For us, it's more a tradeoff rather than an aversion. There's pros (manual memory management in C) and cons (manual memory management in C) for each. We do math operations (dense and sparse matrix math for setting up and solving massive systems of differential equations) on massive graphs with up to billions of nodes and edges. We use C in parts of the engine because we need to manage memory at a…

What parts of it can't just be compiled as C++ code? (unless it has to do with the subtle difference in implicit lifetime object rules) IMO it's much easier to write resleaks/double-frees with refcounted objects in C than it is in C++

VLAs, named structure assignment, sane treatment of the void type, having different "lifetimes" for object (the C understanding of object) existence and initialization, having different namespaces for composed types and variables, a local error handling convention, leading to better error messages, robuster behaviour and a feeling for completeness, a lot of examples of the article and here in the thread, and most importantly no magic.

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

#139
post #113

Earlier quoted context omitted.

Yes, you need to have that to have an OOP language. OOP is object-oriented _Programming_, it's about how you program, not what features the language has.

In hindsight, I had your remark confused with another remark insisting that struct inode_operations is a vtable, despite it having what would be static member functions in C++, which are never in vtables, and there being no inheritance hierarchy. If you are disciplined enough to do what you said, then I could see that as being OOP, but the context here is of something that is not OOP and only happens to overlap with…

I'm also thinking that these kind of vtables in the linux kernel are what would be implemented by the compiler in C++. But because its self-written, you can be much more creative and do other things, that weren't possible if this would be created by a compiler.

Of course you could implement the same in C++ and then it can't be the same as the vtable introduced by the compiler, so you would just end up with to vtables, you own and the one introduced by the compiler.

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

#140
post #132
post #115

Earlier quoted context omitted.

Crashing is optional, depending on error model of the language. C has pitiful error model, thus you'll usually end up jumping to 0... but I recall at least one C environment where that gave you an error back instead of crash. As far as OOP is concerned, lack of implementation is not an issue in instantiating something - an object will just not understand the message, possibly catastrophically.

I was referring to POSIX functions when talking about stubs versus unimplemented functions. Messaging in a programming language is a different animal; one that I have yet to fully understand. Objective C for example resolves messages to function calls, so they look like function calls to me. I would love to know how they differ, but I have never dug into it.

Semantically, most OOP models[1] (even C++) involve "messages" that are "sent" to an object. "Methods" are "how do I handle this kind of message".

This usually resolves to a function call because it's the easiest and most sensible way to do it.

Objective-C is more explicit about it due to Smalltalk heritage. Some languages model objects as functions (closures) that one calls with the "message" (an old trick in various FP languages is to implement a trivial object system with closures for local state).

[1] Arguably CLOS with Generic Functions can be seen as outlier, because the operation becomes centerpiece, not the object.

Post reply on HN