A comprehensive lesson on defensive programming techniques in Python, designed to teach robust software development practices through hands-on examples, assignments, and real-world applications.
This course covers five essential defensive programming modules, each building upon the previous to create a complete understanding of error handling, validation, and robust code design in Python. Perfect for intermediate Python developers looking to write more reliable, maintainable code.
- Python 3.8 or higher
- Basic understanding of Python syntax and object-oriented programming
- Familiarity with testing concepts (helpful but not required)
-
Clone the repository:
git clone <repository-url> cd defensive_programming_lesson
-
Create and activate virtual environment:
# Using venv python -m venv defensive_programming_env source defensive_programming_env/bin/activate # Linux/Mac # or defensive_programming_env\Scripts\activate # Windows # Using conda conda create -n defensive_programming python=3.8 conda activate defensive_programming
-
Install dependencies:
pip install -r requirements.txt
-
Verify installation:
python -m pytest --version pylint --version
-
Run initial tests to verify setup:
pytest --tb=short
Each module follows a consistent learning path designed for progressive skill building:
"Easier to Ask for Forgiveness than Permission" vs "Look Before You Leap"
- Core Concepts: Exception handling philosophies, when to use each approach
- Practical Skills: Performance implications, code readability, race condition prevention
- Real-world Applications: File operations, API calls, concurrent programming
- Key Files:
learning_path.md- Complete learning guidestarter_example.py- Introduction examplesassignment_a.py- Basic assignmentsassignment_b.py- Advanced scenariosextra_exercises.md- 15 additional challenges
Maintaining Code Contracts and Defensive Checks
- Core Concepts: Class invariants, method preconditions/postconditions, assertion strategies
- Practical Skills: Debugging with assertions, performance considerations, assertion placement
- Real-world Applications: Data validation, algorithm correctness, state management
- Key Files:
learning_path.md- Comprehensive guidestarter_example.py- Invariant examplesassignment_a.py- Class invariantsassignment_b.py- Complex systemsextra_exercises.md- 15 practice problems
Custom Exceptions and Error Boundary Design
- Core Concepts: Exception inheritance, custom exception design, error boundaries
- Practical Skills: Exception chaining, error context preservation, recovery strategies
- Real-world Applications: API error handling, system integration, user experience design
- Key Files:
learning_path.md- Detailed pathwaystarter_example.py- Exception patternsassignment_a.py- Custom exceptionsassignment_b.py- Error boundariesextra_exercises.md- 15 advanced scenarios
Formal Contracts and Specification-Driven Development
- Core Concepts: Preconditions, postconditions, class invariants, contract verification
- Practical Skills: Contract-driven design, mathematical verification, formal specifications
- Real-world Applications: Financial systems, mathematical libraries, critical software
- Key Files:
learning_path.md- Contract methodologystarter_example.py- Contract examplesassignment_a.py- Basic contractsassignment_b.py- Advanced systemsextra_exercises.md- 15 contract challenges
Error Signaling Patterns and Observability
- Core Concepts: Sentinel values vs exceptions, logging strategies, observability patterns
- Practical Skills: Error signaling design, log level management, debugging techniques
- Real-world Applications: Service monitoring, debugging production issues, error reporting
- Key Files:
learning_path.md- Complete guidestarter_example.py- Pattern examplesassignment_a.py- Sentinel patternsassignment_b.py- Logging systemsextra_exercises.md- 15 practical exercises
# Run all tests with coverage
pytest --cov --cov-report=html
# Run specific module tests
pytest module_1_eafp_vs_lbyl/ -v
# Run tests with detailed output
pytest --tb=long -v
# Run only failed tests from last run
pytest --lf
# Run tests in parallel (if pytest-xdist installed)
pytest -n auto# Run pylint on all modules
pylint module_*/*.py
# Run pylint on specific module
pylint module_1_eafp_vs_lbyl/*.py
# Run with configuration file
pylint --rcfile=.pylintrc module_*/*.py
# Check specific files only
pylint module_1_eafp_vs_lbyl/assignment_a.pyThe project includes configuration for:
- pytest: Comprehensive testing with coverage reporting
- pylint: Code quality and style checking
- GitHub Actions: Automated testing on multiple Python versions
- Start with Module 1 (EAFP vs LBYL) to understand fundamental philosophies
- Work through starter examples before attempting assignments
- Use the learning path guides in each module for structured progression
- Focus on understanding concepts before optimizing for performance
- Review all starter examples to understand the teaching approach
- Jump directly to Assignment B in each module for challenging scenarios
- Explore extra exercises for advanced real-world applications
- Consider contributing additional examples or improvements
- Use modules as workshop material (each module = 2-3 hour session)
- Adapt assignments to reflect your specific domain challenges
- Create team-specific exercises based on your codebase patterns
- Establish coding standards based on defensive programming principles
- Read the learning path: Each module has a comprehensive guide
- Run starter examples: Understand the concepts with working code
- Complete assignments incrementally: Start with part A, then part B
- Run tests frequently: Use TDD approach when possible
- Check code quality: Run pylint before submitting
# Test specific assignment
pytest module_1_eafp_vs_lbyl/test_assignment_a.py -v
# Test with coverage for specific file
pytest --cov=module_1_eafp_vs_lbyl.assignment_a module_1_eafp_vs_lbyl/test_assignment_a.py
# Debug failing tests
pytest module_1_eafp_vs_lbyl/test_assignment_a.py::test_function_name -v -sEach module is evaluated on:
- Correctness: All tests pass and requirements are met
- Defensive Programming: Proper error handling and validation
- Code Quality: Clear, readable, maintainable code
- Documentation: Adequate comments and docstrings
- Testing: Additional test cases for edge conditions
We welcome contributions! Please see areas where you can help:
- Additional real-world examples
- More challenging exercises
- Improved documentation
- Bug fixes and code improvements
- Translation to other languages
- Books: "Effective Python" by Brett Slatkin, "Clean Code" by Robert Martin
- Documentation: Python Exception Handling
- Tools: pytest documentation, pylint user guide
- Standards: PEP 8, PEP 257
Upon completing all modules with passing tests, you'll have demonstrated proficiency in:
- Exception handling strategies and best practices
- Code contract design and implementation
- Error boundary architecture
- Logging and observability patterns
- Defensive programming principles
Total Learning Time: 15-20 hours (3-4 hours per module) Prerequisites: Intermediate Python knowledge Certification: Self-assessed through comprehensive test suite