Back to all reviewers

Clear abstraction boundaries

chef/chef
Based on 3 comments
Ruby

Design APIs with clear and consistent abstraction boundaries to maintain code quality and prevent interface leakage between different system layers.

API Ruby

Reviewer Prompt

Design APIs with clear and consistent abstraction boundaries to maintain code quality and prevent interface leakage between different system layers.

Key principles:

  1. 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
    
  2. 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
    
  3. 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.

3
Comments Analyzed
Ruby
Primary Language
API
Category

Source Discussions