Legacy Code X-Ray — Powered by IBM Bob 2.0

🏆 Hackathon Entry (SP)2 NeuralX ✓ Transformation Complete

A full before-vs-after analysis of the URL Shortener monolith — refactored by IBM Bob 2.0 into a clean, secure, modular Node.js application.

⚠ Before (Legacy) ✓ After (Bob Refactored)

Toggle dims the inactive state across all metrics and panels.

📊 Metrics Comparison
📁
Codebase Structure
Before
1
Monolithic God File
index.js — 400+ lines
After
6
Modular files
routes · db · validators · utils
🌀
Cyclomatic Complexity
Before
18
High risk — 7-level deep
nested conditionals
After
3
Low — guard clauses
& single-responsibility fns
🔁
Code Duplication
Before
28%
Copy-pasted validation
loops across routes
After
0%
Shared validateUrl()
utility — DRY principle
🔒
Security Posture
Before
High Risk
SQL injection via string
concat · no try/catch
After
Safe
Parameterized queries
full error handling
🧪
Test Coverage
Before
0%
No test files, no runner
configured
After
90%+
Jest unit + integration
tests for all routes
📖
Documentation
Before
None
0 docstrings · no README
no architecture docs
After
Full
JSDoc on every fn
README + arch diagram
💻 Code Diff Viewer
⚠ Before — Copy-pasted messy loops
✓ After — Clean reusable validator
// POST /api/shorten — inline validation
if (data) {
  if (data.url) {
    var temp = data.url;
    if (typeof temp === 'string') {
      if (temp.length > 0) {
        if (temp.length <= 2048) {
          if (temp.startsWith('http')) {
            var flag = true;
            for (var i=0;i<temp.length;i++){
              if (temp[i] === ' ') {
                flag = false;
              }
            }
            if (flag) {
              var arr = temp.split('.');
              if (arr.length >= 2) {
                // ... finally do the work
              } else {
                res.status(400).send({'err':'bad domain'});
              }
            }
          }
        }
      }
    }
  }
}

// PUT /api/urls/:code — same checks copy-pasted again!
if (body) {
  if (body.url) {
    var u = body.url;
    if (typeof u === 'string') {
      if (u.length > 0) {
        if (u.startsWith('http')) {
          // ... identical 7-level nesting again
        }
      }
    }
  }
}
// validators/url.validator.js
/** Validate a URL string. Returns null on success,
 *  or an error message string on failure. */
function validateUrl(url) {
  if (!url || typeof url !== 'string')
    return 'url must be a non-empty string';
  if (url.length > 2048)
    return 'url too long';
  if (!url.startsWith('http://') &&
      !url.startsWith('https://'))
    return 'invalid protocol';
  if (url.includes(' '))
    return 'url cannot contain spaces';
  if (!url.split('.')[1])
    return 'invalid domain format';
  return null; // valid
}

module.exports = { validateUrl };


// routes/shorten.js — reuse everywhere
const err = validateUrl(req.body.url);
if (err) return res.status(400).json({ err });
// ... proceed with the work


// routes/update.js — same validator, zero duplication
const err = validateUrl(req.body.url);
if (err) return res.status(400).json({ err });
// ... proceed with the work
⚠ Before — 7-layer pyramid of doom
✓ After — Clean guard clauses
// POST /api/shorten — original nesting
app.post('/api/shorten', function(x, res2) {
  var data = x.body;          // depth 1
  if (data) {
    if (data.url) {           // depth 2
      var temp = data.url;
      if (typeof temp==='string'){// depth 3
        if (temp.length>0) {  // depth 4
          if (temp.length<=2048){// depth 5
            if (temp.startsWith(  // depth 6
                'http')) {
              if (flag) {        // depth 7
                if(arr.length>=2){ // depth 8!
                  db.run(q, fn);
                }
              }
            }
          }
        }
      }
    }
  }
});
// routes/shorten.js — guard clauses
router.post('/', async (req, res) => {
  const { url, code } = req.body;

  // Guard 1 — validate URL
  const urlErr = validateUrl(url);
  if (urlErr)
    return res.status(400).json({ err: urlErr });

  // Guard 2 — validate custom code
  if (code) {
    const codeErr = validateCode(code);
    if (codeErr)
      return res.status(400).json({ err: codeErr });
  }

  // Happy path — only reached if all guards pass
  const shortCode = code || generateCode();
  const result = await db.insertUrl(shortCode, url);
  res.status(201).json(result);
});
⚠ Before — Raw string concatenation (SQL injection)
✓ After — Parameterized queries
// INSERT — index.js line 218
var q = "INSERT INTO urls " +
  "(code, original_url, clicks, created_at) " +
  "VALUES ('" + code + "', '"
         + temp + "', 0, '"
         + new Date().toISOString()
         + "')";

// ⚠ Attacker input: url = "x'; DROP TABLE urls;--"
db.run(q, function(err) {
  // No error check — silently ignores failures
  var obj = { id: this.lastID, code };
  res2.status(201).send(obj);
});


// UPDATE — same pattern, same risk
var q2 = "UPDATE urls SET original_url='"
       + newUrl
       + "' WHERE code='"
       + code + "'";
db.run(q2);
// db/queries.js — parameterized everywhere

const insertUrl = (code, url) =>
  new Promise((resolve, reject) => {
    const sql = `INSERT INTO urls
      (code, original_url, clicks, created_at)
      VALUES (?, ?, 0, ?)`;
    db.run(
      sql,
      [code, url, new Date().toISOString()],
      function(err) {
        if (err) return reject(err);
        resolve({ id: this.lastID, code, url });
      }
    );
  });


const updateUrl = (code, newUrl) =>
  new Promise((resolve, reject) => {
    const sql = `UPDATE urls
      SET original_url = ?
      WHERE code = ?`;
    db.run(sql, [newUrl, code],
      err => err ? reject(err) : resolve());
  });
🏗 Architecture Viewer
⚠ Before — Monolithic "God File"
index.js
~400 lines · 1 file
HTTP Server DB Init Routing Validation Business Logic DB Queries HTML Template Error Handling Code Generation Redirect Logic Click Tracking

Everything tangled into a single file — impossible to test,
extend, or maintain independently.

✓ After — Clean Modular Layered Architecture
app.js & server.js Entry Point · HTTP Bootstrap
↓
routes/ shorten · urls · redirect
↓
validators/ url.validator · code.validator
↓
utils/ generateCode · formatResponse
↓
db/ connection · queries (parameterized)
↓
tests/ unit tests · integration tests · 90%+ coverage

Each layer has a single responsibility —
independently testable, replaceable, and extensible.

−83%
Complexity Reduction
100%
SQL Injection Fixed
+90%
Test Coverage Gained
6×
More Modular Files
−28%
Code Duplication Removed
∞
Docs Written (from zero)