Detailed plan for 15 improvements across 6 phases covering security, stability, robustness, testability, modernization, and build. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
15 KiB
Regelwerk — Implementierungsplan für DeepSeek V4 Flash
Ziel: 15 Verbesserungen in 6 Phasen. Jede Änderung ist atomar, verifizierbar und einzeln commitbar. Wichtig: Keine Änderung ohne vorheriges
gitnexus_impact. Nach jedem Commit: Build + Tests +gitnexus_detect_changes.
Phase A — Sicherheit (3 Änderungen)
A1. Dangling Pointer in regelmaschine.cpp beheben
Datei: src/core/regelmaschine.cpp
Vorher:
MSMem fallMem("regelFall FallMem", 1024*1024);
gFallMemObject = &fallMem;
Nachher:
gFallMemObject = new MSMem("regelFall FallMem", 1024*1024);
Entsprechend am Ende der Funktion: Kein delete (Ownership liegt beim Global, wie gPersistParamMemObject).
Ablauf:
gitnexus_impact({target: "gFallMemObject", direction: "upstream"})— alle Zugriffsstellen identifizierengitnexus_impact({target: "regelFaelle", direction: "upstream"})— Caller prüfensrc/core/regelmaschine.cppöffnen, Zeile mitMSMem fallMem(...)suchenMSMem fallMem(...)durchgFallMemObject = new MSMem(...)ersetzen- Alle folgenden
&fallMem-Referenzen durchgFallMemObjectersetzen - Build:
cmake --build build -j$(sysctl -n hw.logicalcpu) - Tests:
ctest --test-dir build --output-on-failure - Integrationstest:
./build/tests/integration_test - Address Sanitizer:
cmake -B build-asan -G Ninja -DBUILD_TESTS=ON -DCMAKE_CXX_FLAGS="-fsanitize=address" && cmake --build build-asan && ./build-asan/tests/integration_test gitnexus_detect_changes()- Commit:
fix: dangling pointer gFallMemObject → heap allocation
A2. Thread-sichere Singleton-Initialisierung
Datei: src/core/initrw.cpp
Vorher:
static bool fInit = false;
if(fInit)
return true;
fInit = true;
// ~40 mapXxx = makeMap(...)
Nachher:
#include <mutex>
static std::once_flag initFlag;
bool alreadyDone = false;
std::call_once(initFlag, [&]() {
alreadyDone = true;
// ~40 mapXxx = makeMap(...)
});
if(alreadyDone) return true;
Oder einfacher: fInit durch std::atomic<bool> ersetzen und den Check+Set mit exchange machen.
Ablauf:
gitnexus_impact({target: "initRegelwerk", direction: "upstream"})src/core/initrw.cppöffnen,#include <mutex>hinzufügenstatic bool fInit = false→static std::atomic<bool> fInit{false}if(fInit) return true;→if(fInit.load(std::memory_order_acquire)) return true;fInit = true;→fInit.store(true, std::memory_order_release);- Build + Tests + Integrationstest
gitnexus_detect_changes()- Commit:
fix: thread-safe initialization via std::atomic<bool>
A3. strcpy-Audit — kritische Stellen entschärfen
Betroffene Dateien (priorisiert):
| Datei | Zeile | Änderung |
|---|---|---|
src/domain/class_regelbegruendung.cpp |
25 | strcpy(dst, src) → strncpy(dst, src, sizeof(dst)-1); dst[sizeof(dst)-1]='\0' |
src/domain/class_leistungwert.cpp |
40 | strcpy(buf, val) → strncpy(buf, val, sizeof(buf)-1); buf[sizeof(buf)-1]='\0' |
src/rw_actions/op_datum_selektor.hpp |
22 | strcpy(opdatum_, val) → sichern |
src/rw_actions/setze_alpha_extension.hpp |
33 | strcpy(gop, lst→gop()) → sichern |
Ablauf:
gitnexus_impact({target: "class_regelbegruendung", direction: "upstream"})für jede betroffene Klasse- Jede Datei einzeln bearbeiten
- Vor jeder Änderung: Größe des Ziel-Puffers ermitteln (
sizeof(buf)oder Member-Deklaration prüfen) strcpy(dst, src)→strncpy(dst, src, sizeof(dst)-1); dst[sizeof(dst)-1] = '\0';- Nach jeder Datei: Build + Tests
gitnexus_detect_changes()- Commit pro Datei:
fix: replace strcpy with strncpy in <filename>
Nicht anfassen: src/util/std_c_compat.hpp — nur dokumentieren, nicht ändern (wird von vielen Dateien benötigt).
Phase B — Stabilität (3 Änderungen)
B1. static → thread_local für Funktions-Caches
Datei: src/core/sys_vars.cpp
3 Stellen ändern:
diagnosenErfuellt()—static ScheinPtrVector sScheine→thread_local ScheinPtrVector sScheinehatFK4012Quartal()—static ScheinPtrVector sScheine→thread_local ScheinPtrVector sScheineaktive_bht_datum_menge()—static std::vector<int> s_result→thread_local std::vector<int> s_result
Ablauf:
src/core/sys_vars.cppöffnen- Drei
static→thread_localersetzen (einfaches Search & Replace) - Build + Tests + Integrationstest
- Thread Sanitizer:
cmake -B build-tsan -G Ninja -DBUILD_TESTS=ON -DCMAKE_CXX_FLAGS="-fsanitize=thread" && cmake --build build-tsan && ./build-tsan/tests/integration_test gitnexus_detect_changes()- Commit:
fix: function-local static caches → thread_local in sys_vars.cpp
B2. sRegelnAusfuehren atomar machen
Dateien: src/core/regelmaschine.hpp, src/core/regelmaschine.cpp
Ablauf:
regelmaschine.hpp:#include <atomic>hinzufügenstatic bool sRegelnAusfuehren;→static std::atomic<bool> sRegelnAusfuehren{true};regelmaschine.cpp: Alle Zugriffe aufsRegelnAusfuehrenprüfen:- Lesend:
if(sRegelnAusfuehren)→if(sRegelnAusfuehren.load(std::memory_order_acquire)) - Schreibend:
sRegelnAusfuehren = val→sRegelnAusfuehren.store(val, std::memory_order_release)
- Lesend:
- Build + Tests
gitnexus_detect_changes()- Commit:
fix: sRegelnAusfuehren → std::atomic<bool>
B3. DLL-Interface mit Mutex schützen
Datei: src/core/rw_dll.cpp
Ablauf:
gitnexus_impact({target: "xmlRegelWerk", direction: "upstream"})— alle Callergitnexus_impact({target: "RegelWerkFree", direction: "upstream"})— alle Callerrw_dll.cppöffnen,#include <mutex>hinzufügen- File-scope:
static std::mutex rwMutex;hinzufügen xmlRegelWerk(): Erste Zeile nach Variablen-Deklarationen →std::lock_guard<std::mutex> lock(rwMutex);RegelWerkFree(): Erste Zeile →std::lock_guard<std::mutex> lock(rwMutex);- Build + Tests + Integrationstest
gitnexus_detect_changes()- Commit:
fix: mutex guard for DLL interface functions
Phase C — Robustheit (2 Änderungen)
C1. Exception-Sicherheit — class_steuer.cpp:73
Datei: src/domain/class_steuer.cpp
Vorher:
catch(...) {
Debug::logError("...");
}
Nachher:
catch(const std::exception& e) {
Debug::logError(std::string("...") + e.what());
return false;
}
catch(...) {
Debug::logError("... unknown exception");
return false;
}
Ablauf:
gitnexus_impact({target: "class_steuer", direction: "upstream"})class_steuer.cppöffnen,#include <exception>prüfen/ergänzencatch(...)durch die differenzierte Variante ersetzen- Prüfen ob
return falsebereits vorhanden ist, sonst ergänzen - Build + Tests
gitnexus_detect_changes()- Commit:
fix: distinguish exception types in class_steuer.cpp
C2. ConfigUnion → std::variant
Datei: src/core/config.hpp (und alle Includer)
Vorher:
union ConfigUnion {
char* s;
int i;
char c;
void* p;
double d;
};
Nachher:
#include <variant>
using ConfigUnion = std::variant<char*, int, char, void*, double>;
Ablauf:
gitnexus_impact({target: "ConfigUnion", direction: "upstream"})— ALLE Zugriffsstellen finden (critical!)- Alle Zugriffe auditieren:
union.member→std::get<T>(variant).s→std::get<char*>(val)oderstd::get<0>(val).i→std::get<int>(val)oderstd::get<1>(val)- usw.
- Alle Zugriffe einzeln ersetzen
- Build — erwarte Compile-Fehler an Stellen mit
.member-Zugriff, die übersehen wurden → fixen - Tests
gitnexus_detect_changes()- Commit:
refactor: ConfigUnion → std::variant
Phase D — Testbarkeit (3 strategische Änderungen)
D1. Testabdeckung: Prädikate Batch 2
Neue Datei: tests/predicates_batch2_test.cpp
Struktur (Kopie von predicates_batch1_test.cpp):
#define CATCH_CONFIG_RUNNER
#include "catch2/catch_amalgamated.hpp"
#include "mock_leistung.hpp"
// Predicate-Headers includieren
TEST_CASE("GOP_Menge_Selector", "[predicates]") {
// Test mit MockLeistung
}
Zu testende Prädikate (10 Stück):
gop_menge_selector.hpp— GOP-Mengen-Prüfungist_element_von.hpp— Set-Membershipnicht_disjunkt.hpp— Nicht-Disjunktheitpruefe_patientenalter.hpp— Altersprüfungist_op_datum.hpp— OP-Datum-Prüfungdiagnosen_erfuellt.hpp— Diagnose-Prüfungle_hat_berechtigung.hpp— LE-Berechtigungkennzeichen_ist_element_von.hpp— Kennzeichen-Prüfunghat_datum.hpp— Datums-Prüfungist_gueltiges_datum.hpp— Gültiges-Datum-Prüfung
Ablauf:
predicates_batch1_test.cpplesen — Pattern verstehenmock_leistung.hpplesen — MockLeistung API verstehen- Jeden Predicate-Header lesen —
operator()Signatur + Parameter verstehen - Test-Struktur: Pro Predicate mindestens 2 Test Cases (true + false)
tests/CMakeLists.txtergänzen:add_rw_catch_test(predicates_batch2_test)- Build +
./build/tests/predicates_batch2_test gitnexus_detect_changes()- Commit:
test: predicates batch 2 — 10 standalone Prädikate
D2. Testabdeckung: Aktionen Batch 1
Neue Datei: tests/actions_batch1_test.cpp
Zu testende Aktionen (10 Stück):
leistung_hinzu_dahinter.hpp— Leistung einfügenwertaenderung.hpp— Wertänderungproz_wertaenderung.hpp— Prozentuale Wertänderungumfaerbe.hpp— Umfärbentaetigkeit_umsetzen.hpp— Tätigkeit umsetzensetze_lug.hpp— LUG setzensetze_lglug.hpp— LGLUG setzengop_hinzusetzen.hpp— GOP hinzusetzengop_menge_hinzu.hpp— GOP-Menge hinzusetze_alpha_extension.hpp— Alpha-Extension setzen
Ablauf:
actions_test.cpplesen — Pattern verstehenmock_leistung.hpplesen — welche Setter/Methoden existieren für Aktionen- Jeden Action-Header lesen —
operator()Signatur verstehen - Tests schreiben (pro Action: Setup → Ausführen → Assertions auf MockLeistung)
tests/CMakeLists.txtergänzen- Build +
./build/tests/actions_batch1_test gitnexus_detect_changes()- Commit:
test: actions batch 1 — 10 standalone Aktionen
D3. Integrationstest für sb_meth-Familie
Neue Datei: tests/sb_meth_integration_test.cpp
Ansatz: XML-Testdaten → Patientenfall::newFromXML() → regelFall() → Ergebnis-XML → Assertions
Ablauf:
integration_test.cpplesen — Pattern verstehen (XML laden, Patient erstellen, Regelwerk ausführen)- Test-XML-Dateien für SB20, SB34, SB46 erstellen (minimale Testszenarien)
- Tests schreiben:
TEST_CASE("SB20 - basic", "[integration][sb]") - Erwartete Ergebnisse im Ausgabe-XML prüfen (Leistung gestrichen, umgefärbt, etc.)
tests/CMakeLists.txtergänzen- Build +
./build/tests/sb_meth_integration_test gitnexus_detect_changes()- Commit:
test: integration tests for SB methods
Phase E — Modernisierung (3 Bereiche)
E1. Makros in rw_macros.hpp ersetzen
Datei: src/core/rw_macros.hpp
Ersetzungen (schrittweise, je ein Commit):
-
FOR/REP→for(size_t i = s; i < n; ++i)(direkt, keinstd::views::iotawegen Compiler-Support)gitnexus_impact({target: "FOR", direction: "upstream"})→ alle Verwendungen finden- Jede Verwendung einzeln ersetzen
- Makro am Ende entfernen
-
RW_ARRAYSIZE→std::sizegitnexus_impact({target: "RW_ARRAYSIZE", direction: "upstream"})RW_ARRAYSIZE(arr)→std::size(arr)(benötigt#include <iterator>)- Makro entfernen
-
LL→std::int64_tgitnexus_impact({target: "LL", direction: "upstream"})- Alle
LL-Verwendungen durchstd::int64_tersetzen #include <cstdint>wo nötig
-
ALL→ direkte Iterator-Paare- Nicht ersetzen, sondern dokumentieren dass es deprecated ist
- Zu viele Verwendungen für einen simplen Batch
Ablauf pro Makro:
- Impact-Analyse
- Alle Verwendungen ersetzen
- Build — Compile-Fehler an übersehenen Stellen fixen
- Tests
- Makro-Definition entfernen
gitnexus_detect_changes()- Commit
E2. Tote Perl-Tools löschen
Zu löschende Dateien:
tools/make.pl
tools/clean.pl
tools/test_rw.pl
tools/rw_mr.pl
tools/gen2list.pl
tools/idstring.pl
Ablauf:
git rm tools/make.pl tools/clean.pl tools/test_rw.pl tools/rw_mr.pl tools/gen2list.pl tools/idstring.pl- Build — sicherstellen dass nichts fehlschlägt (diese Tools sind nicht im Build)
gitnexus_detect_changes()- Commit:
chore: remove dead Perl build tools (hpux, borland, sybase, svn era)
E3. Tote Konfigurationen und Plattform-Guards
Teil 1 — config/kvai.ini:
git rm config/kvai.ini
Teil 2 — src/util/debug.cpp _HPUX-Guards:
- Zeilen mit
#ifdef _HPUX/#ifndef _HPUX/#endifidentifizieren (~Zeilen 20, 445) _HPUX-Block komplett entfernen (Code zwischen#ifdefund#else/#endif)- Build — sicherstellen dass nichts fehlschlägt
Teil 3 — src/util/debug.cpp __WIN32__-Guards:
- Prüfen ob Windows noch ein Target ist (CI baut nur Linux)
- Wenn nicht:
__WIN32__-Block entfernen - Wenn doch: so belassen
Teil 4 — src/aktsource_dummies/ leeres Verzeichnis:
rmdir src/aktsource_dummies
Ablauf:
- Jeweils einzeln ausführen
- Build nach jeder Änderung
gitnexus_detect_changes()- Commits:
chore: remove dead HP-UX platform guardsetc.
Phase F — Build (1 Änderung)
F1. Toten RW_DLL-Define entfernen
Dateien: CMakeLists.txt, src/core/rw_implementation.cpp
Ablauf:
CMakeLists.txt:add_compile_definitions(RW_DLL)entfernensrc/core/rw_implementation.cpp:#ifdef RW_DLL-Block + Code darin prüfen — wenn DLL-spezifisch und DLL nicht mehr gebaut wird → entfernen- Build — wenn Compile-Fehler durch fehlende
#ifdef RW_DLL-Definitionen → prüfen ob Code noch gebraucht wird - Tests
gitnexus_detect_changes()- Commit:
chore: remove dead RW_DLL define and guards
Verifikation nach jeder Phase
# In Projekt-Root ausführen:
# 1. Build
cmake -B build -G Ninja -DBUILD_TESTS=ON
cmake --build build -j$(sysctl -n hw.logicalcpu)
# 2. Alle Tests
ctest --test-dir build --output-on-failure
# 3. Integrationstest separat
./build/tests/integration_test
# 4. Statische Analyse
cppcheck --enable=all --inconclusive src/ 2>&1 | head -50
# 5. gitnexus_detect_changes()
npx gitnexus detect-changes
Checkliste pro Änderung
gitnexus_impact— Blast Radius verstanden, Risiko akzeptabel- Code-Änderung — nur das Nötigste, existierenden Stil respektieren
- Build —
cmake --build builderfolgreich - Tests —
ctest --test-dir build --output-on-failurealle grün - Integrationstest —
./build/tests/integration_testerfolgreich gitnexus_detect_changes— nur erwartete Symbole betroffen- Commit — ein Commit pro logischer Änderung, Sprache Deutsch
Geschätzte Gesamtanzahl Commits: ~20–25
| Phase | Commits |
|---|---|
| A | 5 (A1=1, A2=1, A3=3) |
| B | 3 |
| C | 2 |
| D | 3 |
| E | 8 (E1=4, E2=1, E3=3) |
| F | 1 |