Skip to content

Three duplicated conversion paths in LibraryService #4

Description

@lgnap

Context

LibraryService is 870 lines long and carries three structurally identical conversion methods:

Method Line Length
addConvertedRawPackFile 212 83 lines
addConvertedArchivePackFile 297 75 lines
addConvertedFsPackFile 374 76 lines

All three follow the same sequence, in the same order:

sourceIdentity(packPath)          // observed before reading
createTempFile(packPath, suffix)
<reader>.read(fis)                // try-with-resources on the source
asset (de)compression
<writer>.write(pack, fos)         // try-with-resources on the target
recordProvenance(...)             // observed after, compared with the first observation

Only the reader, the writer, the suffix, the direction of compression and the log wording
differ. Everything else — temporary file handling, the ordering of the provenance
observations, error handling — is duplicated three times.

The cost is concrete, and this fork's own provenance mechanism illustrates it well: it rests on
a subtle invariant (observe the source identity both before and after, record only if the two
agree) that must now be maintained correctly in three places. A fix applied to only two of them
would go unnoticed — ConversionProvenanceTest covers all six conversions today, but nothing
guarantees that will still hold for the seventh.

Description

Extract the shared skeleton into a single parameterised path, preserving observable behaviour
exactly. The existing provenance and stream-lifecycle tests (ConversionProvenanceTest,
ConversionStreamLifecycleTest, ConversionVerificationTest) are the safety net: they must
pass unmodified, before and after. If they need touching, the refactor changed behaviour.

Affected files

  • web-ui/src/main/java/studio/webui/service/LibraryService.java — the extraction
  • web-ui/src/test/java/studio/webui/service/ConversionProvenanceTest.java — unchanged, net
  • web-ui/src/test/java/studio/webui/service/ConversionStreamLifecycleTest.java — same
  • web-ui/src/test/java/studio/webui/service/ConversionVerificationTest.java — same

Implementation plan

  1. Run the web-ui suite and record the green starting state.
  2. Extract a private method holding the skeleton — provenance observation, temporary file,
    read, transform, write, record — parameterised by reader, writer, suffix and asset
    transform.
  3. Rewrite the three public methods as calls into that skeleton, keeping their signatures,
    their preconditions (the "already in archive format" rejections) and their log messages
    identical.
  4. Verify the three test classes above pass without having been touched.
  5. Optional, to assess separately: LibraryService is still large after the extraction.
    Moving conversion into a dedicated class would be consistent, but widens the review — only
    worth doing if the first step goes smoothly.

Acceptance criteria

  • A single copy of the conversion sequence
  • Public signatures, preconditions and log messages unchanged
  • The three conversion test classes pass without modification
  • No new tests required — this is a refactor, not a change
  • mvn -Dskip.installnodeyarn=true -Dskip.yarn=true test green on Linux and Windows

Complexity

M — mechanical, but over code whose provenance invariant is subtle: take small steps.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions