3.2 KiB
| title | category | severity |
|---|---|---|
| Anti-Patterns in Stemwijzer | anti-patterns | critical |
Anti-Patterns
NOTE: Some anti-patterns below were investigated and found to be resolved or invalid. See individual entries for details.
CRITICAL: print() Instead of Logging
File: api_client.py
Evidence: 11 instances of print(f"...") instead of _logger.info(...)
Broken code:
def get_motions(self, ...):
try:
# ...
print(f"Fetched {len(voting_records)} voting records from API") # BAD
print(f"Processed into {len(motions)} unique motions") # BAD
except Exception as e:
print(f"Error fetching motions from API: {e}") # BAD - no traceback
Fix:
import logging
_logger = logging.getLogger(__name__)
def get_motions(self, ...):
try:
_logger.info("Fetched %d voting records from API", len(voting_records))
_logger.info("Processed into %d unique motions", len(motions))
except Exception as e:
_logger.exception("Error fetching motions from API: %s", e)
return []
CRITICAL: Global _DummySt Replacement
File: explorer.py
Evidence: Lines ~50-70, module-level st = _DummySt() global replacement
Problem: Creates a module-level variable st that shadows streamlit module, causing subtle bugs.
Fix: Use conditional flags instead of global replacement:
# GOOD: Use conditional logic
try:
import plotly.express as px
import plotly.graph_objects as go
HAS_PLOTLY = True
except ImportError:
HAS_PLOTLY = False
px = None
go = None
def render_chart(data):
if not HAS_PLOTLY:
_logger.warning("Plotly not available")
return
# ... rest of chart logic
WARNING: Logger Naming Inconsistency
Evidence: 16 files use logger, 17 files use _logger
Files with logger (without underscore):
- api_client.py, ai_provider.py, pipeline files, analysis files
Files with _logger (with underscore):
- database.py, explorer.py, explorer_helpers.py
Recommendation: Standardize on _logger for module-level loggers.
WARNING: Bare except with pass
File: database.py, line 47
# BAD - catches KeyboardInterrupt, SystemExit, MemoryError
try:
conn.execute("CREATE SEQUENCE IF NOT EXISTS motions_id_seq START 1")
except: # bare except
pass
Fix:
try:
conn.execute("CREATE SEQUENCE IF NOT EXISTS motions_id_seq START 1")
except Exception as exc:
_logger.debug("Sequence creation skipped: %s", exc)
INVESTIGATED: Entity-ID / Party-Name Mismatch
Status: INVALID - investigated and resolved
Investigation Summary: svd_vectors.entity_id only contains MP names (not party names). Party centroids are correctly computed via mp_metadata lookups. No production bug exists.
Pattern: Three Separate Party Alias Dictionaries
Problem: Party name variations exist in 3+ places with no canonical alias mapping.
Fix: Create one PARTY_ALIASES dict in config.py:
PARTY_ALIASES = {
"GroenLinks-PvdA": ["GL-PvdA", "GroenLinks PvdA", "PvdA-GroenLinks"],
"PVV": ["Partij voor de Vrijheid"],
# ...
}