---
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"],
    # ...
}
```
