--- title: Anti-Patterns in Stemwijzer category: anti-patterns severity: 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**: ```python 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**: ```python 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: ```python # 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 ```python # BAD - catches KeyboardInterrupt, SystemExit, MemoryError try: conn.execute("CREATE SEQUENCE IF NOT EXISTS motions_id_seq START 1") except: # bare except pass ``` **Fix**: ```python 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`: ```python PARTY_ALIASES = { "GroenLinks-PvdA": ["GL-PvdA", "GroenLinks PvdA", "PvdA-GroenLinks"], "PVV": ["Partij voor de Vrijheid"], # ... } ```