You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
127 lines
3.2 KiB
127 lines
3.2 KiB
---
|
|
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"],
|
|
# ...
|
|
}
|
|
```
|
|
|