In the past months I\'ve asked for people here on SE and on other sites offer me
ID: 642468 • Letter: I
Question
In the past months I've asked for people here on SE and on other sites offer me some constructive criticism regarding my code. There's one thing that kept popping out almost every time and I still don't agree with that recommendation; :P I'd like to discuss it here and maybe things will become clearer to me.
It's regarding the single-responsibility principle (SRP). Basically, I have a data class, Font, that not only holds functions for manipulating the data, but also for loading it. I'm told the two should be separate, that loading functions should be placed inside a factory class; I think this is a mis-interpretation of the SRP...
A Fragment from My Font Class
class Font
{
public:
bool isLoaded() const;
void loadFromFile(const std::string& file);
void loadFromMemory(const void* buffer, std::size_t size);
void free();
void some();
void another();
};
Suggested Design
class Font
{
public:
void some();
void another();
};
class FontFactory
{
public:
virtual std::unique_ptr<Font> createFromFile(...) = 0;
virtual std::unique_ptr<Font> createFromMemory(...) = 0;
};
The suggested design supposedly follows the SRP, but I disagree
Explanation / Answer
There's nothing wrong with that code in my opinion, it does what you need it to in a sensible and reasonably easy to maintain manner.
However, the problem that you have with this code is that if you want it to do anything else you're going to have to change it all.
The point of the SRP is that if you have a single component 'CompA' that does algorithm A() and you need to change algorithm A() you shouldn't have to change 'CompB' as well.
My C++ skills are too rusty to suggest a decent scenario where you will need to change your font management solution, but the usual case I make is the idea of sliding in a caching layer. Ideally you don't want the thing that loads stuff to know about where it comes from, nor should the thing being loaded care where it comes from, because then making changes is simpler. It's all about maintainability.
One example might be you loading your font from a third source (say a character sprite image). In order to achieve this you will need to change your loader (to call the third method if the first two fail) and the Font class itself to implement this third call. Ideally, you'd just make another factory (SpriteFontFactory, or whatever), implement the same loadFont(...) method and stick it in a list of factories somewhere that can be used to load the font.
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.