Wszystkie powtarzające się wywołania HQL zostały przeniesione do jednego szablonu. Dzięki temu klasa DBCache całkiem przyjemnie teraz wygląda.
Na przykład obsługa ustawień stała się trywialna:
class DBCache { private { Cache!(KeyValue, "key") keyValues; // ... } // ... KeyValue getValue(const string key) { return keyValues.get(key); } void setValue(T)(const string key, const T value) { keyValues.setOrUpdate(key, (KeyValue v) => v.value = value.to!string); } } |
Przekazanie funkcji ustawiającej wartość jako parametru funkcji setOrUpdate jest całkiem wygodne i wszechstronne, ale nie jest niczym niezwykłym – podobne funkcjonalności oferują C++, C#, Java oraz zapewne inne języki. Chciałbym natomiast zwrócić uwagę na inicjalizację zmiennych w tej klasie:
this(DBSession s) { import std.traits; foreach(n; FieldNameTuple!DBCache) { alias ElementType = typeof(mixin("this." ~ n)); static if(isInstanceOf!(CacheElement, ElementType)) { mixin("this." ~ n) = ElementType(s); } } this.session = s; } |
W widocznym powyżej konstruktorze inicjalizuję wszystkie elementy klasy, których typ jest konkretyzacją szablonu CacheElement. Tak potężna introspekcja jest wedle mojej wiedzy unikalna dla D (mowa o językach kompilowanych). Często gdy piszę w C++ brakuje mi tego – ale znów kieruję moje nadzieje ku C++20 i reflexpr.
Jeśli chodzi o Pieruna to czas zabrać się za dodanie komentarzy.