Hi,
nach längerer Zeit melde ich mich mal wieder (und muss ein wenig aufarbeiten).
Die Aussagen bezüglich der RAII-Templateklasse kann ich nicht hachvollziehen. Die theoretische Argumentation erinnert mich gerade an "angelernte" Informatik-Lehrer. Man kann mit jedem Template müll schreiben, wenn man nicht weiß was man da machen soll. Mein Tipp: Dokumentation lesen.
Wer den Kopieroperator betrachtet und die isRAII()-Methode findet, müsste eigentlich klar erkennen was die Klasse macht. Aber nun gut, ist meine Designader und muss nicht jedermanns Geschmack sein. Der Weg führt auch nach Rom.
Was ich hier stellenweise allerdings als "Tipps" lese, empfinde ich als grauenvoll. Besonders das mit den Konstruktoren macht mir Design-Alpträume. Aber nur mal so nebenbei:
a) Return codes sind ja mittlerweile unbeliebt und Exceptions empfohlen. Also wenn ich nun eine Exception im Konstruktor werfe - ist das nicht gegen alle Designrichtlinien?
b) Wenn der Benutzer zu faul ist sich die Dokumentation der Klasse anzusehen, dann wird er auch im Konstruktor nur Müll reinschreiben. Wie wärs mal mit nullptr im Parameter "einfach so aus Lust". Mein Gegenvorschlag: In jeder Funktion die Resourcen auf Gültigkeit der Werte prüfen - ist viel besser in der Fehlerauswertung.
Was ich mich auf frage (@Male): Was willst du mit deiner Engine erreichen? Ist es wirklich
notwendig alles in abertausende Templates zu zerstückeln nur um für alle Engines vorzubereiten? Wie groß und wichtig ist die Kundschaft für die andere API? Reicht es am Anfang nicht, erst einmal
ein Grundsystem anzufertigen? Hier werden Infos vermisst, was du genau machen möchtest. Dann muss man auch nicht mehr so allgemein schreiben.
Ich werde auch etwas stutzig, weil ein schreiben einer abstrakten Klasse und dann späteres auslöschen dessen Funktion ziemlich... sinnbefreit ist. Du solltest im Bereich der abstrakten Klassen vielleicht nochmal eine practical session einlegen, um das System und den Sinn dieser Klassen zu verdeutlichen.
Zudem solltest du dich an ein einheitliches Design gewöhnen. Es ist einfach für den Kunden praktisch, wenn er folgendes weiß: "Für jede Ressource, die ich benötige, muss ich die create()-Methode aufrufen und die Parameter ausfüllen. Wenn ich mal spezielles machen möchte, habe ich mit getInstance() die Möglichkeit die Ressource direkt zu benutzen. Um die Zerstörung der Ressource kümmert sich die Klasse automatisch.".
"Doof" ist: "Für jede Klasse gibt es ein spezielles Template. Dort wird definiert was die Klasse kann. Man kann nur die Funktionen aufrufen, die dort auch definiert sind. Je nach Einsatz muss ich eine beliebig definierte Create##XY()-Funktion aufrufen und die Parameter definieren. Später muss ich dann Release##XY() aufrufen".
Ich habe eher gute Erfahrungen gemacht, die Anwender auf ein einheitliches System zu drillen. Der Kunde weiß wo er suchen muss und mache Dinge ergeben von sich aus eine Erklärung. Und das muss auch das Ziel sein: Selbsterklärendes Design.
Und wirklich alles in eine Klasse zu packen, ist unübersichtlich, funktionell überladen und schlecht wartbar. Es sollten eher einzelne Klassen ineinander greifen. Und
viel später kann man dann ein paar Klassen in einer gemeinsamen Klasse erweitern: VertexBuffer + IndexBuffer + MaterialBufferGeneral => MeshBuffer.
Alles nur Anregungen...
Aber schlussendlich muss jeder wissen was er selber (oder im Team) macht.