Live data from Hacker News

Object-oriented design patterns in C and kernel development

oshub.org

51–60 of 224 posts

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

#51
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…

Inheritance is not needed when a composite pattern can be used. class DefaultTask { } class SpecialTask { } class UsedItem { UsedItem() { _task = new SpecialTask() } void DoIt() { _task.DoIt() } } Is python a OOP language? Self / this / object pointer has to be passed similar to using C style object-oriented / data abstraction.

The interesting thing is, that in the OOP implementation inheritance IS composition of vtables and data. It's really only syntactic sugar, that is sometimes not unambiguous.

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

#52
post #11
post #3

Earlier quoted context omitted.

I largely agree, and use these patterns in C, but you’re neglecting the usual approach of having a default or stub implementation in the base for classic OOP. There’s also the option of using interfaces in more modern OOP or concept-style languages where you can cast to an interface type to only require the subset of the API you actually need to call. Go is a good example of this, in fact doing the lookup at runtime…

My point is that this pattern is not object oriented programming. As for a default behavior with it, you usually would do that by either always adding the default pointer when creating the structure or calling the default whenever the pointer is NULL. In the Linux VFS for example, there are optimized functions for reading and writing, but if those are not implemented, a fallback to unoptimized functions is done at th…

> My point is that this pattern is not object oriented programming.

Isn't this exactly how most (every?) OOP language implements it? You would say a C++ virtual method isn't OOP?

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

#53
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…

Inheritance is not needed when a composite pattern can be used. class DefaultTask { } class SpecialTask { } class UsedItem { UsedItem() { _task = new SpecialTask() } void DoIt() { _task.DoIt() } } Is python a OOP language? Self / this / object pointer has to be passed similar to using C style object-oriented / data abstraction.

Python doesn't require self to be passed. You need it in method definitions, but not calls.

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

#54
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.

> In Smalltalk and Objective-C, you just check at runtime whether an object instance responds to a message. This is the original OOP way. This introduces performance issues larger than the typical ones associated with vtable lookups. Not all domains can afford this today and even fewer in the 80s/90s when these languages were first designed. > It's sad that OOP was corrupted by the excessively class-centric C++ and J…

> This introduces performance issues larger than the typical ones associated with vtable lookups.

Don't know about other programming languages but with Objective-C due to IMP caching the performance is close to C++ vtable

  Name Iterations Total time (sec) Time per (ns)
  C++ virtual method call 1000000000 1.5 1.5
  IMP-cached message send 1000000000 1.6 1.6

https://mikeash.com/pyblog/friday-qa-2016-04-15-performance-...

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

#55

I always wonder, why not anything similar made it into a new (some) C version? Clearly, there is a significant demand for - lots of people reimplementing the same (similar) set of patterns.

Whenever you invent syntactic sugar you need to make some usage blessed and some usage impossible/needing to fallback to the old way without syntactic sugar. See https://news.ycombinator.com/item?id=45040662. Also some point of C is, that it doesn't hide that dynamic complexity. You always see when there is dynamic dispatch. There are tons of language, which introduce some formalism for these concepts, honestly most modern imperative languages seem to be. The unique selling point of C is, that you see the complexity. That influences you to only use it if you really want it. Also the syntax isn't really that complicated.

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

#56
post #44
post #41

Earlier quoted context omitted.

“this” is a reserved keyword in C++, so you do not need to worry about it being a global variable. That said, I like having a this pointer explicitly passed as it is in C with ADTs. The functions that do not need a this pointer never accidentally have it passed from the developer forgetting to mark the function static or not wanting to rewrite all of the function accesses to use the :: operator.

It’s not about ‘this’ being a global, it’s if you see ‘i++’ in code it’s not obvious if ‘i’ is a member or not without having to check context.

Good point. I had misunderstood the previous comment as suggesting that this be passed to the member function as an explicit argument, rather than requiring dereferences of this be explicit. The latter makes far more sense and I agree it makes reasoning about things much easier.

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

#57
post #24

Earlier quoted context omitted.

I think both of these invocations are invalid. Using object1's vtable methods on object2, obviously, but in the latter case: the vtable method should just point at the superclass impl, if not overridden. And if overridden and the child impl needs to call the superclass, it can just do so without dispatching through some vtable.

When you think of vtables as unique or owned by an object, then these example seem weird to you. When you think of them as orthogonal to your types/objects, these examples can be useful. In the first example, object1 and object2 can very much be of the same type or compatible types/subtypes/supertypes. Having vtables per object as opposed to per class to me indicates, that it IS intended to modify the behaviour of an…

"Orthogonal" vtables are essentially traits/typeclasses.

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

#58
post #45
post #44

Earlier quoted context omitted.

It’s not about ‘this’ being a global, it’s if you see ‘i++’ in code it’s not obvious if ‘i’ is a member or not without having to check context.

If you see "i++" in code and you don't have any context about what "i" is, then what difference does it make if "i" is a member variable, global variable, parameter, etc etc... If all you see in code is a very tiny 3 character expression, you won't be able to make much of a judgement about it to begin with.

Not allowing a variable to implicitly refer to a member variable makes it much easier to find. If it is not declared in the function and there is no implicit dereferencing of a this pointer, the variable is global. If the variable name is commonly used and it is a member variable, it is a nightmare to hunt for the correct declaration in the codebase with cscope.

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

#59
post #34

A few years ago Peterpaul developed a lightweight object-oriented system on top of C that was really pleasant to use[0]. No need to pass in the object explicitly, etc. Doesn't have the greatest documentation, but has a full test suite (e.g., [1][2]). [0] https://github.com/peterpaul/co2 [1] https://github.com/peterpaul/co2/blob/master/carbon/test/pas... [2] https://github.com/peterpaul/co2/blob/master/carbon/test/pas…

For people wondering what it looks like without the syntactic sugar of carbon then look here [0]. As far as I can see, there's no support for parametric polymorphism.

0. https://github.com/peterpaul/co2/tree/master/examples/my-obj...

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

#60

Yup. I've often wonder why the aversion to C++ since they are obviously using objects. Is it that they don't want to also enable all the C++ language junk like templates or OO junk like inheritance?

C makes it obvious were you use that dynamism and where you don't. Syntactic sugar doesn't really make that much of a difference and also restricts more creative uses.

The C syntax is not really that complicated. Dynamic dispatch and virtual methods was already in the article. Here is inheritance:

    struct Subclass {
        struct Baseclass base;
    };
That's not really that complicated. Sure, you need to encapsulate every method of the parent class, if you want to expose it. But you are also recommended to do that in other languages, and if you subclass you probably want to slightly modify behaviour anyway.

As for stuff like templates: C doesn't thinks everything needs to be in the compiler. For example shadowing and hiding symbols can be done by the linker, since this is the component that handles symbol resolution across different units anyway. When you want templates, either you actually want a cheap way of runtime dynamism, then do that, or you want source code generation. Why does the compiler need to do that? For the basics there is a separate tool in the language: the Preprocessor, if you want more, you are free to choose your tool. If you want a macro language, there is e.g. M4. If you want another generator just use it. If you feel no tool really cuts it, why don't you write your code generator in C?

Post reply on HN