Geçtiğimiz aylarda burada SE ve diğer sitelerdeki insanlar için kodumla ilgili bazı yapıcı eleştiriler sundum. Neredeyse her seferinde ortaya çıkan bir şey var ve hala bu öneriye katılmıyorum; : P Burada tartışmak istiyorum ve belki de işler bana daha açık hale gelecektir.
Tek sorumluluk prensibi (SRP) ile ilgilidir. Temelde, Font
sadece veri manipüle etmek için değil, aynı zamanda onu yüklemek için fonksiyonları tutan bir veri sınıfı var. İkisinin ayrı olması gerektiği, yükleme fonksiyonlarının fabrika sınıfına yerleştirilmesi gerektiği söylendi; Bence bu, SRP'nin yanlış bir yorumu ...
Yazı Tipi Sınıfımdan Bir Parça
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();
};
Önerilen Tasarım
class Font
{
public:
void some();
void another();
};
class FontFactory
{
public:
virtual std::unique_ptr<Font> createFromFile(...) = 0;
virtual std::unique_ptr<Font> createFromMemory(...) = 0;
};
Önerilen tasarım SRP'yi takip ediyor, ancak katılmıyorum - sanırım çok ileri gidiyor. Font
Sınıf artık kendi kendine yeterli (o fabrikanın olmadan hiçbir işe yaramaz) ve değildir FontFactory
ihtiyaçlar ayrıca uygulanmasını maruz muhtemelen dostluk veya kamu getters aracılığıyla yapılır kaynak, uygulanması, ilgili ayrıntıları bilmek Font
. Bence bu daha çok parçalanmış bir sorumluluk vakası .
İşte bu yüzden yaklaşımımın daha iyi olduğunu düşünüyorum:
Font
kendi kendine yeter - Kendi kendine yeterli olmak, anlamak ve sürdürmek daha kolaydır. Ayrıca, başka bir şey eklemek zorunda kalmadan sınıfı kullanabilirsiniz. Bununla birlikte, daha karmaşık bir kaynak yönetimine (bir fabrika) ihtiyacınız olduğunu fark ederseniz, bunu da kolayca yapabilirsiniz (daha sonra kendi fabrikam hakkında konuşacağımResourceManager<Font>
).Standart kitaplığı izler - Kullanıcı tanımlı türlerin, ilgili dilde standart türlerin davranışını kopyalamak için mümkün olduğunca denemesi gerektiğine inanıyorum.
std::fstream
Kendi kendine yeterli olduğunu ve benzeri işlevleri sağlaropen
veclose
. Standart kütüphaneyi takip etmek, çabaları öğrenmek için çaba harcamaya gerek olmadığı anlamına gelir. Ayrıca, genel olarak konuşursak, C ++ standart komitesi muhtemelen tasarım hakkında buradakinden daha fazla şey biliyor, bu yüzden şüpheniz varsa ne yaptıklarını kopyalayın.Test edilebilirlik - Bir şeyler ters gidiyor, sorun nerede olabilir? -
Font
Verilerini işleme şekliFontFactory
mi yoksa verileri yükleme şekli mi? Gerçekten bilmiyorsun. Sınıfların kendi kendine yeterli olması bu sorunu azaltır: tek başına test edebilirsinizFont
. Daha sonra fabrikayı test etmeniz gerekiyorsa veFont
iyi çalıştığını biliyorsanız, bir sorun olduğunda fabrikanın içinde olması gerektiğini de bilirsiniz.Bu bağlam agnostik - (Bu benim ilk nokta ile biraz kesişir.) Bir
Font
şey yapar ve onu nasıl kullanacağınız hakkında herhangi bir varsayımda bulunmaz: istediğiniz gibi kullanabilirsiniz. Kullanıcıyı fabrika kullanmaya zorlamak, sınıflar arasındaki bağlantıyı artırır.
Benim de bir fabrikam var
(Çünkü tasarımı Font
bana izin veriyor.)
Ya da daha çok bir yönetici, sadece bir fabrika değil ... Font
kendi kendine yeterlidir, bu yüzden yöneticinin nasıl inşa edileceğini bilmesine gerek yoktur ; bunun yerine yönetici aynı dosya veya ara belleğin birden fazla belleğe yüklenmemesini sağlar. Bir fabrikanın da aynısını yapabileceğini söyleyebilirsiniz, ama bu SRP'yi bozmaz mı? O zaman fabrika sadece nesne inşa etmekle kalmaz, aynı zamanda onları da yönetir.
template<class T>
class ResourceManager
{
public:
ResourcePtr<T> acquire(const std::string& file);
ResourcePtr<T> acquire(const void* buffer, std::size_t size);
};
İşte yöneticinin nasıl kullanılabileceğine dair bir gösteri. Temelde bir fabrikada kullanıldığına dikkat edin.
void test(ResourceManager<Font>* rm)
{
// The same file isn't loaded twice into memory.
// I can still have as many Fonts using that file as I want, though.
ResourcePtr<Font> font1 = rm->acquire("fonts/arial.ttf");
ResourcePtr<Font> font2 = rm->acquire("fonts/arial.ttf");
// Print something with the two fonts...
}
Sonuç olarak...
(Bu bir tl koymak istiyorum; dr, ama bir tane düşünemiyorum.: \)
Eh, işte orada, davamı olabildiğince iyi yaptım. Lütfen sahip olduğunuz karşı argümanları ve önerilen tasarımın kendi tasarımım üzerinde olduğunu düşündüğünüz avantajları gönderin. Temel olarak, bana yanlış olduğumu göstermeye çalış. :)