Prompt
Design APIs with clear and consistent abstraction boundaries to maintain code quality and prevent interface leakage between different system layers.
Key principles:
- Separate CLI and API interfaces: CLI tools should not return API-style responses, and API endpoints should not handle CLI-specific concerns.
# Incorrect - CLI tool returning HTTP-like response { "status" => 200, "message" => "Success" } if @calling_request != "CLI" # Better approach - wrap the functionality with appropriate interfaces def perform_upload # Upload functionality here return true # Simple boolean for CLI end def api_upload perform_upload { "status" => 200, "message" => "Success" } # HTTP-style response for API end - Use proper method signatures: Prefer explicit keyword arguments over option hashes for better readability, documentation, and forward compatibility.
# Avoid this pattern - hard to document, using a generic options hash def powershell_exec(script, options = {}) timeout = options.fetch(:timeout, nil) # ... end # Better pattern - explicit keyword arguments with defaults def powershell_exec(script, interpreter: :powershell, timeout: nil) # Implementation... end - Place functionality at the appropriate abstraction level: Methods and properties should exist at the level where they are most logically connected.
# Avoid adding HTTP-specific error handling in generic resources class Resource # This doesn't belong here - too specific private def http_request_errors source.map do |msg| uri = URI.parse(msg) "Error connecting to #{msg} - Failed to open TCP connection to #{uri.host}:#{uri.port}" end end end # Better: Place in the specific resource that needs it class RemoteFileResource < Resource private def http_request_errors # Implementation... end end
Following these principles creates more maintainable, testable, and adaptable code by ensuring that each component has a clear, focused responsibility.