Hacker News new | ask | show | jobs
by Const-me 1640 days ago
> just a thin and often clunky layer of syntactic sugar on top of it.

That sugar does help.

C allows adding another function pointer to that structure, but not set that pointer. C++ compiler forces programmers to implement all interface methods. Forget to override a method, the code which instantiates the class won’t compile complaining about not being able to instantiate an abstract class.

Code navigation is another thing. In visual studio, while the cursor is over an abstract method, F12 key looks up all implementations of the abstract class, and populates the “find symbol results” panel with a clickable list of the implementations of the method. With visual assist addon installed, Alt+G key does the same only presents the results in a popup menu instead of a separate panel.

Both things are borderline useless for small projects, but IMO they help a lot for medium to large ones, especially developed by multiple people.

1 comments

> That sugar does help.

I've never found it very compelling. As I said there are also downsides, inflexible implementation that is implementation specific (so it can be difficult to manipulate with low level assembly).

> C allows adding another function pointer to that structure, but not set that pointer. C++ compiler forces programmers to implement all interface methods. Forget to override a method, the code which instantiates the class won’t compile complaining about not being able to instantiate an abstract class.

Never found that particularly helpful if the code is structured well. You'd either allow for NULL implementations to be default or error not implemented at least until all subsystems are converted, or the initialization functions that all object allocations should call (because the code is well written) can verify all required fields are set. If you want to be even cleverer, you can probably do static initialization checks at least where your fields are constant and have those compile down to nothing just checked at compile time.

> Code navigation is another thing. In visual studio, while the cursor is over an abstract method, F12 key looks up all implementations of the abstract class, and populates the “find symbol results” panel with a clickable list of the implementations of the method. With visual assist addon installed, Alt+G key does the same only presents the results in a popup menu instead of a separate panel.

I can see how that might help a little, although surely with some minimal scripting a symbol browsing tool should be able to be taught about similar patterns like find all functions that are assigned to this particular member of a structure of function pointers. Although I don't use IDEs or any symbol tagging tools just grep usually, so maybe I'm a luddite.

With a nice code base that follows reasonable conventions and naming, it's pretty easy to find e.g., if you have a structure-of-function-pointers style of thing then you can find all definitions of "struct address_space_operations" or if a function pointer member is called page_mkwrite, then you search for *_page_mkwrite and get ext4_page_mkwrite, xfs_page_mkwrite, btrfs_page_mkwrite, etc. (which are not always strictly enforced in Linux but at least if you are searching for \.page_mkwrite you can usually easily see non-confirming names).

> Both things are borderline useless for small projects, but IMO they help a lot for medium to large ones, especially developed by multiple people.

I don't see that it helps a lot, and even as syntactic sugar I don't see it being a big advancement in the scheme of things.

> Never found that particularly helpful if the code is structured well

IMO, all else being equal, errors detectable at compile-time should be detected at compile-time. Following reasons. (1) No matter the circumstances like time pressure, compiler errors are impossible to ignore, because they fail the build (2) Compiler errors are easier to detect automatically, e.g. many projects have automatic build systems. Even if the project has automatically run unit tests, people still need to write these tests first, i.e. the process is not completely automatic. (3) Runtime checks have runtime costs. Even if the checks are in static initializers or similar, that’s still runtime cost at startup and/or first use. Compile-time checks are free at runtime, makes the code faster.

> although surely with some minimal scripting a symbol browsing tool should be able to be taught about similar patterns

Technically, yes. Practically, two things. If you’re part of a team of developers, in particular if that team is remote, people are using their own computers, and people have varying levels of programming experience, such scripting tools are hard to implement. Another thing, the time spent making and supporting these tools is the time not spent improving the product being built.

> IMO, all else being equal, errors detectable at compile-time should be detected at compile-time.

I agree and you can do that with C. See compiletime_assert in Linux. An ops table definition or registration macro can do compile time checking that such fields are populated.

> Technically, yes. Practically, two things. If you’re part of a team of developers, in particular if that team is remote, people are using their own computers, and people have varying levels of programming experience, such scripting tools are hard to implement. Another thing, the time spent making and supporting these tools is the time not spent improving the product being built.

In all teams I've been part of including the loosely coupled and highly distributed open source side of kernel development, tools are widely shared and developed together. People don't just get left out in the wilderness. The bigger the project the more true this is.

I get that standard IDE niceness exists for some OOP language features, so it might be some small practical advantage, it just isn't an inherent advantage of the OOP paradigm. We don't need to use C++ to get nice rich and context aware editing search/display.

> An ops table definition or registration macro can do compile time checking

If programmers writes that check, yes. Same applies to a unit test. C++ compiler gonna verify that thing automatically, no extra work required, neither initially, not over the lifetime of the project.

> tools are widely shared and developed together

I prefer when a freshly cloned repository builds without any extra tools on a freshly installed computer, with either F7 in the correct version of Visual Studio, or something like cmake ../ && make in Linux shell, after installing the required dependencies from the official package repository of that Linux. In my experience, custom tools are often a pain in the long run.

> it just isn't an inherent advantage of the OOP paradigm

The paradigm is orthogonal to programming languages. I think OOP is merely a high-level design pattern where objects keeping their private state only accessible/modifiable by calling methods of these objects.

In this sense, the source code linked above in this thread is 100% OOP, despite plain C. Just like the majority of Linux APIs which operate on opaque handles: open/close/read/write for files, snd_pcm_* functions for ALSA, all these IOCTL requests for V4L2, various handles for Vulkan. All these APIs are implementing an abstraction over external devices with very complicated internal mutable state, OOP is pretty much the only way to go for these things.

> If programmers writes that check, yes. Same applies to a unit test. C++ compiler gonna verify that thing automatically, no extra work required, neither initially, not over the lifetime of the project.

Yes. Programmers have to write these checks, that's all about what a well structured and maintained codebase is about. They have to write many checks no matter what the language, because missing initializers is one tiny little aspect of things you might want to check for.

> I prefer when a freshly cloned repository builds without any extra tools on a freshly installed computer, with either F7 in the correct version of Visual Studio, or something like cmake ../ && make in Linux shell, after installing the required dependencies from the official package repository of that Linux. In my experience, custom tools are often a pain in the long run.

I didn't suggest otherwise, I was talking about editing and searching scripts and commands.

> The paradigm is orthogonal to programming languages.

Right, C can do it. As I said in the beginning, I don't like the OOP features of C++ because they're clunky inflexible and hardly any benefit in terms of easier syntax.

> I think OOP is merely a high-level design pattern where objects keeping their private state only accessible/modifiable by calling methods of these objects.

No "OOP" is definitely considered to be language features too.