Shift register library design I am creating a small library for controlling bars of leds and have some doubts about my design.

I have 2 basic entities in the design so far:

BarService (and implementation)

template&lt;class T&gt;

class BarService{
public:
  virtual void turnOnLeds(T* bar, int end) = 0;


class PinBarService : public BarService&lt;PinBar&gt;{
public:
  virtual void turnOnLeds(PinBar* bar, int end);
  void initPins(PinBar* bar);
};


class OpampService : public BarService&lt;OpampBar&gt;{
public:
  virtual void turnOnLeds(OpampBar* bar, int end);
  void initPins(OpampBar* bar);
};


Bar models:

class Bar{
private:
  int ledCount;
public:
  Bar(int ledCount);
  int getLedCount();
};


class BasicBar : public Bar{
private:
  int* pins;
public:
  BasicBar(int ledCount, int pins[]);
  int getPin(int index);
};


class OpampBar : public Bar{
private:
  int input;
public:
  OpampBar(int ledCount, int input);
};


My reasoning for separating these is that I feel the Bar models should only contain information about themselves, thus allowing me to create more classes later on which use that information rather than having the bar itself perform actions (like writing to hardware).

The reason I'm having doubts is that by using templates every implementation of the service needs to accept a different model.

My question comes down to: Am I going overboard with separating the model from its actions? and are templates a good solution here? and overall, what could be improved about this design?
Generally "template vs polymorphism" is a complex topic. A simple rule of thumb: if it is high level (e.g., service you instantiate a few times) go virtual, if it is low level (you need to create a array of million these objects) then go template.

In your case... honestly your interface makes little sense to me - it is difficult to make any advices.

Say, is there any point in Bar class? It simply holds an int and serves no other purpose. Just having a common function and variable doesn't imply that you need to have a shared basic class. If it had virtual destructor then I could understand to a certain degree.

Why OpampBar is a class? It just holds two integers. Why not make it a struct with public members? Why make it unnecessarily complicated?

What is this BasicBar and what is this pins raw pointer? Is it a pointer to an array? A pointer to data that doesn't belong to it? Why not use std::vector&lt;int&gt;? There are lots of well made classes and functions in STL, why not utilize them?

What is the point of BarService? It is an interface class. I know of two purposes of interface classes: (1) To allow your program to switch between different derived classes easily. (2) Hide implementation. Is this the case? (Well, it can also serve as poor man's concept substitude... but I doubt that you use any SFINAE).

You need to watch and read tutorials on C++. There are plenty for free - just google it. There are lots of CppCon videos on YouTube where they explain additions to C++ (you gotta learn what was added in C++11/14 as well as what STL already had for 20 years).