Fortplot's module architecture follows the Single Responsibility Principle (SRP) to maintain files under 1,000 lines while preserving backward compatibility through facade patterns.
The original fortplot_pdf.f90 (415 lines) was refactored into focused submodules:
fortplot_pdf.f90                     (415 lines) - Main facade module
├── fortplot_pdf_core.f90            (110 lines) - Core types and constants  
├── fortplot_pdf_text.f90            (498 lines) - Text rendering and fonts
├── fortplot_pdf_drawing.f90         (232 lines) - Drawing primitives
├── fortplot_pdf_axes.f90            (392 lines) - Axes and tick rendering
└── fortplot_pdf_io.f90              (261 lines) - Stream I/O operations
Usage Pattern:
! Client code remains unchanged - uses the facade
use fortplot_pdf, only: pdf_context, create_pdf_canvas
type(pdf_context) :: ctx
call create_pdf_canvas(ctx, "output.pdf", 800, 600)
fortplot_animation.f90 reduced to 48 lines through dependency injection:
! Core animation type with minimal dependencies
type :: animation_t
    procedure(animate_interface), pointer, nopass :: animate_func => null()
    integer :: frames = 0
    integer :: interval_ms = DEFAULT_FRAME_INTERVAL_MS
contains
    procedure :: run
    procedure :: save
end type animation_t
fortplot.f90 (233 lines) maintains comprehensive API through selective imports:
module fortplot
    ! Re-export core functionality
    use fortplot_figure_core, only: figure_t
    use fortplot_animation, only: animation_t, FuncAnimation
    use fortplot_colors, only: color_t
    ! Stateful API procedures
    public :: plot, scatter, contour, show, savefig
    public :: figure, xlabel, ylabel, title, legend
end module fortplot
All refactored modules maintain 100% API compatibility:
! Before refactoring - works unchanged
use fortplot_pdf
type(pdf_context) :: ctx
call create_pdf_canvas(ctx, "plot.pdf", 800, 600)
! After refactoring - identical usage
use fortplot_pdf  ! Now imports from facade
type(pdf_context) :: ctx
call create_pdf_canvas(ctx, "plot.pdf", 800, 600)
Main facade modules re-export functionality from submodules:
module fortplot_pdf
    ! Import specialized functionality
    use fortplot_pdf_core
    use fortplot_pdf_text
    use fortplot_pdf_drawing
    use fortplot_pdf_axes
    use fortplot_pdf_io
    ! Re-export public interfaces
    public :: pdf_context, create_pdf_canvas
    public :: draw_pdf_axes_and_labels, draw_mixed_font_text
end module fortplot_pdf
DO:
! Import from facade modules for compatibility
use fortplot_pdf, only: pdf_context
! Access specialized functionality when needed
use fortplot_pdf_text, only: draw_mixed_font_text
DON'T:
! Avoid direct imports that bypass the facade
use fortplot_pdf_core, only: pdf_context_core  ! Too specific
Example:
! Add to fortplot_pdf_drawing.f90
subroutine draw_new_primitive(ctx, ...)
end subroutine
! Re-export in fortplot_pdf.f90
module fortplot_pdf
    use fortplot_pdf_drawing, only: draw_new_primitive
    public :: draw_new_primitive
end module
Keep modules under limits: - Target: < 500 lines per module - Hard limit: < 1,000 lines per module - Functions: < 100 lines each (target < 50)
Check sizes:
wc -l src/fortplot_pdf*.f90
No build system changes required - FPM automatically handles: - Module dependency resolution - Compilation order - Interface checking
Dependencies resolved automatically through use statements:
! fortplot_pdf.f90 depends on:
use fortplot_pdf_core      ! Core types
use fortplot_pdf_text      ! Text rendering  
use fortplot_pdf_drawing   ! Drawing ops
use fortplot_pdf_axes      ! Axes rendering
use fortplot_pdf_io        ! I/O operations
Verify facade pattern maintains compatibility:
! Test original API still works
program test_api_compatibility
    use fortplot_pdf
    type(pdf_context) :: ctx
    call create_pdf_canvas(ctx, "test.pdf", 400, 300)
    ! ... existing test code unchanged
end program
Ensure clean separation of concerns:
! Each submodule tested independently
program test_pdf_text_module
    use fortplot_pdf_text, only: draw_mixed_font_text
    ! Test text functionality in isolation
end program
Smaller modules improve compilation performance: - Parallel compilation of independent modules - Reduced rebuild scope for changes - Better compiler optimization opportunities
Facade pattern adds minimal overhead: - No additional function call layers - Module imports resolved at compile time - Same machine code generation as monolithic modules
No changes required - all existing code continues working unchanged.
Monitor these files approaching size limits:
fortplot_figure_core.f90: Currently 49 lines (safe)fortplot.f90: 233 lines (well within limits)fortplot_animation.f90: 48 lines (excellent modularization)Apply same facade pattern when limits approached.