refactor: устранить нарушения DRY, SRP, KISS

- DRY: вынести scoped() в общий ScopedKey (был дублирован в PayloadStore и SharedIndex)
- DRY: вынести чтение словарей и перечитывание файлов в ResourceLoader
  (было дублировано в NameDictionary, ToponymDictionary, SystemsConfig)
- DRY: вынести алгоритм Луна в Validators.luhnCheckDigit (Synthetic переиспользует)
- SRP: вынести константы типов ПД из RuleRegistry в PdTypes
- SRP: вынести проверку организаций из NameDictionary в OrganisationDetector
- KISS: словари оставлены статическими (неизменяемые, детерминированные)

Поведение не изменилось: 1840 тестов проходят, NodeLogsLeakTest по-прежнему
падает на тех же 55 задокументированных утечках.
This commit is contained in:
Максименко Никита Владимирович
2026-09-22 22:39:16 +03:00
parent 6b5a7ae35f
commit aa4c926a8f
19 changed files with 457 additions and 349 deletions
@@ -1,14 +1,7 @@
package ru.pdguard.detect;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Словарь населённых пунктов России — проверка того, что значение, пойманное
@@ -28,9 +21,9 @@ import java.util.stream.Collectors;
*/
public final class ToponymDictionary {
private static final Set<String> SETTLEMENT_STEMS = load("/names/settlements.txt").stream()
private static final Set<String> SETTLEMENT_STEMS = ResourceLoader.set("/names/settlements.txt").stream()
.map(Declension::withoutInflectedEnding)
.collect(Collectors.toUnmodifiableSet());
.collect(java.util.stream.Collectors.toUnmodifiableSet());
private ToponymDictionary() {
}
@@ -58,20 +51,4 @@ public final class ToponymDictionary {
}
return false;
}
private static Set<String> load(String resource) {
try (InputStream in = ToponymDictionary.class.getResourceAsStream(resource)) {
if (in == null) {
throw new IllegalStateException("Словарь не найден в сборке: " + resource);
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) {
return reader.lines()
.map(String::trim)
.filter(line -> !line.isEmpty() && !line.startsWith("#"))
.collect(Collectors.toUnmodifiableSet());
}
} catch (IOException e) {
throw new UncheckedIOException("Не удалось прочитать словарь " + resource, e);
}
}
}
}