> IDK it seems pretty common in the embedded world to add support for a new piece of hardware by copying the entire driver and then changing the parts that the new hardware supports instead of trying to come up with a driver that supports all generations of the hardware.
The rule of three is not exclusive to the embedded world. It´s far better to have duplicate code around then to have to deal with poor generalizations that affect multiple independent modules, which in this case mean hardware support.
To put it in perspective, how many pieces of hardware would you require to re-test and validate if you decided to refactor bits of drivers that might share a common code path?
This might not exist in C (I've never written it), but something like this seems like a fairly clean pattern you could use:
abstract class BaseDriver {
abstract commonThing()
}
abstract class BaseDriverV1 extends BaseDriver {
commonThing() {
console.log('This is the common method implementation for all V1 drivers')
}
abstract doThingOnlyV1Does()
}
class DriverV1_1 extends BaseDriverV1 {
doThingOnlyV1Does() {
console.log('This is how Driver V1.1 does the V1 thing')
}
}
This way you can use either an interface or an "abstract" definition that declares the base driver methods and the versioned driver methods, then provide version-dependent implementations where needed, or else share the common implementations by inheritance/extension.
Maybe this turns into spaghetti at scale and it actually is easier to just copy-paste all of it, who knows.
> This might not exist in C (I've never written it), but something like this seems like a fairly clean pattern you could use:
How sure are you?
I mean, if the code path of a driver is touched, that triggers all verification and validation steps on all pieces of hardware that are required to ensure that the pieces of hardware affected by it will continue to work as expected.
Furthermore, how many bugs are introduced on a daily basis because people like you and me push "fairly clean patterns" that end up triggering all sorts of unexpected consequences? I know I did, and still do, my share.
C doesn't provide any language support for this, including any notion of abstracts or classes. You can still do it manually and that's basically how drivers are implemented in Linux, but it doesn't address the combinatorial test matrix explosion.
The rule of three is not exclusive to the embedded world. It´s far better to have duplicate code around then to have to deal with poor generalizations that affect multiple independent modules, which in this case mean hardware support.
To put it in perspective, how many pieces of hardware would you require to re-test and validate if you decided to refactor bits of drivers that might share a common code path?