An Illustration Of Decoupling - Part I of II

This is a simplified, real-world, design problem that caused rather significant division within a small software development team.  Personally, I thought the best answer was rather obvious but I'd like you to decide.

Context

Consider a web service that reads a file from storage and produces one or more files as output.  For example, lets say it resizes an image to various, standard sizes: sml, med, lge.  The service may process multiple input files in a batch-style request.  File storage identifies a file with a string that may contain forward slashes '/' that indicate a folder structure only by convention.  So folders don't need to be created or deleted.  The input consists of an array of objects (each containing a 'sourceFile' field), and a single 'outputRoot'.

Current Implementation

The current implementation operates as described below.

Request:
{
  inputs: [
    {
      sourceFile: 'my/path0/input0.jpg',
    },

    {
      sourceFile: 'my/path1/input1.jpg',
    },
  ],
  outputRoot: 'my/output/',
}


Resulting files:
  my/output/input0.sml.jpg
  my/output/input0.med.jpg
  my/output/input0.lge.jpg
  my/output/input1.sml.jpg
  my/output/input1.med.jpg
  my/output/input1.lge.jpg


Problem: 

Clients need more control over how outputs are arranged to facilitate more robust batching

Proposal 1: 

This originated from the author of the current solution who has worked in the business domain before and considered the path in each sourceFile input to have significant contextual value.

Add 'sourceRoot' to each input that identifies the portion of the sourceFile that should be ignored.  The absence of a 'sourceRoot' will cause default behaviour which is to use the entire path up to the last '/'.

Request:

{
  inputs: [
    {
      sourceFile: 'my/path0/input0.jpg',
      sourceRoot: 'my/',
    },
    {
      sourceFile: 'my/path1/input1.jpg',
      sourceRoot: 'my/',
    },
  ],
  outputRoot: 'my/output/',
}

Resulting files:
  my/output/path0/input0.sml.jpg
  my/output/path0/input0.med.jpg
  my/output/path0/input0.lge.jpg
  my/output/path1/input1.sml.jpg
  my/output/path1/input1.med.jpg
  my/output/path1/input1.lge.jpg

Proposal 2: 

This originated from a developer who was not that familiar with the business domain and also noticed some other problems with the current solution.

Add 'outputPrefix' to each input that indicates the path (within outputRoot) to write resulting files.  Absence of 'outputPrefix' would indicate the current default behaviour (i.e. use last part of path).

Request:
{
  inputs: [
    {
      sourceFile: 'my/path0/input0.jpg',
      outputPrefix: 'alt0/result0.',
    },
    {
      sourceFile: 'my/path1/input1.jpg',
      outputPrefix: 'alt1/result1.',
    },
  ],
  outputRoot: 'my/output/',
}

 
Resulting files:
  my/output/alt0/result0.sml.jpg
  my/output/alt0/result0.med.jpg
  my/output/alt0/result0.lge.jpg
  my/output/alt1/result1.sml.jpg
  my/output/alt1/result1.med.jpg
  my/output/alt1/result1.lge.jpg

 
Have a think about which proposal you prefer and then read part II which outlines the pros and cons of each solution, and more.

Comments

Popular Posts