Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making sense of frontend code with forensic tec...

Avatar for Richard Richard
November 19, 2025

Making sense of frontend code with forensic techniques (v1) 🇬🇧 @c't webdev 2025

In projects with hundreds of thousands of lines, it is easy to lose track of code, architecture and quality. Are we still on the right track, are we blocking ourselves with internal dependencies, or are we already stuck? Software is immaterial, we cannot see how it is doing.

In this talk, we will therefore look at the forensic techniques and tools we can use to make the quality of code and architecture tangible. The tools extract quantitative information from code, architecture, git history, and the technique qualify these results. Put together we have accurate picture where we stand. This also support us in having a dialog with non-technical stakeholders at eye level about the required quality.

The forensic tools include the open-source tool CodeCharta and DependaCharta.

Avatar for Richard

Richard

November 19, 2025
Tweet

More Decks by Richard

Other Decks in Programming

Transcript

  1. Figures CCO https://www.openpeeps.com/ Slide 2 CC BY-SA richargh.de You there

    Phoenix is not making any sense. They are getting slower and slower. This is Alex This is Alex’ Boss You are now in charge of it. Fix it. Huh? What is Phoenix?
  2. Slide 3 CC BY-SA richargh.de Huh? What is Phoenix? And

    she is already gone. Phoenix is 50k lines… Where do I even start?
  3. Slide 7 CC BY-SA richargh.de I’ll ask Claude Code Prompt:

    What are the biggest issues of this codebase and in what priority should I fix them?
  4. Claude Code * Reads typically use Haiku to figure out

    if the content is safe. ** Ctrl+O in Claude and verified via mitmproxy Gobble up stuff, and send it to the LLM Subagent Explore() 1. Grep(TODO|FIXME|HACK|XXX) 2. Grep(password|secret|token|api_key|apikey) 3. Grep(eval|exec|dangerouslySetInnerHTML) 4. Grep(SELECT.*FROM.*WHERE) 5. Grep(componentWillMount|componentWillReceivePro ps) 6. Grep(race condition|deadlock|mutex|RwMutex) 7. Grep(CVE|vuln) 8. Grep(console.log|error) 9. Bash(npm audit) 10. Bash(npm run test) 11. LineCount(*.ts) 12. LineCount(*.spec.ts) 13. Read(all package.json) 14. Read(all *.md) 15. Read(jest|webpack.config.*) 16. Read(largest files) Slide 8 CC BY-SA richargh.de
  5. Claude Code * Reads typically use Haiku to figure out

    if the content is safe. ** Ctrl+O in Claude and verified via mitmproxy Gobble up stuff, and send it to the LLM Get a report Subagent Explore() 1. Grep(TODO|FIXME|HACK|XXX) 2. Grep(password|secret|token|api_key|apikey) 3. Grep(eval|exec|dangerouslySetInnerHTML) 4. Grep(SELECT.*FROM.*WHERE) 5. Grep(componentWillMount|componentWillReceivePro ps) 6. Grep(race condition|deadlock|mutex|RwMutex) 7. Grep(CVE|vuln) 8. Grep(console.log|error) 9. Bash(npm audit) 10. Bash(npm run test) 11. LineCount(*.ts) 12. LineCount(*.spec.ts) 13. Read(all package.json) 14. Read(all *.md) 15. Read(jest|webpack.config.*) 16. Read(largest files) ## Critical issues 1. MASSIVE TECHNICAL DEBT FROM TODO/FIXME MARKERS 2. SQL INJECTION VULNERABILITIES RISK 3. EXCESSIVE USE OF DANGEROUS REACT PATTERNS 4. DEPRECATED REACT LIFECYCLE METHODS 5. MASSIVE COMPONENT SIZE AND COMPLEXITY 6. INCOMPLETE TEST COVERAGE ## RECOMMENDATIONS ### Immediate (0-30 days) 1. Security Audit SQL Queries 2. Remove console.log statements 3. Patch bootstrap 4. Audit all dangerouslySetInnerHtml Slide 9 CC BY-SA richargh.de
  6. Reliability? Repeatability? * Same prompt three times, /clear after each

    result Get a report Get another report ## Critical issues 1. MASSIVE TECHNICAL DEBT FROM TODO/FIXME MARKERS 2. SQL INJECTION VULNERABILITIES RISK 3. EXCESSIVE USE OF DANGEROUS REACT PATTERNS 4. DEPRECATED REACT LIFECYCLE METHODS 5. MASSIVE COMPONENT SIZE AND COMPLEXITY 6. INCOMPLETE TEST COVERAGE ## RECOMMENDATIONS ### Immediate (0-30 days) 1. Security Audit SQL Queries 2. Remove console.log statements 3. Patch bootstrap 4. Audit all dangerouslySetInnerHtml CRITICAL - Fix Immediately [1-2 weeks] 1. Hardcoded Sentry DSN Exposed 2. SQL Injection Vulnerabilities 3. Weak Cryptography (SHA-1, MD5) HIGH - Address Soon (1-2 months) 1. Monolithic App Layer (130K+ lines) 2. Technical Debt Backlog (TODO/FIXME) 3. Type Safety Issues (2,257 instances Total effort estimate: 715-1,080 hours Logging not mentioned Patching not mentioned Slide 10 CC BY-SA richargh.de Get a third report CRITICAL - Fix Immediately 1. XSS Vulnerability Risk 2. Insecure Cryptographic Hash (SHA-1) 3. Massive File Sizes HIGH - Fix Within Sprint 1. localStorage Security Issues 2. 1,606 TODO/FIXME Comments 3. Excessive any Type Usage Recommended Priority Order Week 1-2 (Security Sprint): 1. Fix XSS vulnerabilities 2. Replace SHA-1 with SHA-256 3. Implement CSP headers 4. Secure localStorage or migrate to HttpOnly cookies SQL not mentioned
  7. Feels similar, with random priority Slide 11 CC BY-SA richargh.de

    999+ SQL Injections Console.logs 999+ Patch 999+ 1 2 3
  8. Some problems 1. The analysis is incomplete 1. Lost in

    the middle context problems1 2. No historic git data used 3. Includes potentially unreachable code or not externally exposed code 2. Does the priority match your expertise? 1. The analysis treats all code files as equally important 2. Files critical for the business should be more important 3. How do I prioritize this over business problems? 1 https://arxiv.org/abs/2307.03172 Slide 13 CC BY-SA richargh.de
  9. Hierarchy of needs Slide 18 CC BY-SA richargh.de Is the

    capacity to act given? Are there any unaccepted/unmitigated risks? If you cannot deploy main, you cannot act. Risks can also be accepted or mitigated. The #flexible part the boss wants adressed
  10. Slide 19 CC BY-SA richargh.de OK. We fixed the necessary

    risk, business accepted the rest. Thinking Have you tried Rude and not very helpful Let me be a bit more specific This is Taylor Now what? The reports have a lot of ideas…
  11. Software Forensics [soft-wer, fuh-ren-ziks], noun – scientific method of solving

    crimes that involve examining code and git to establish facts in code. Often involving investigative tools. Coined by Adam Tornhill, Your Code as a Crime Scene Slide 20 CC BY-SA richargh.de
  12. Slide 21 CC BY-SA richargh.de Facts seem like a good

    idea Well what do you do when you want to find a murderer? I don’t have any idea where to start looking. Of course I, … wait what? A murderer?
  13. Triangulating crimes * The more dimensions, the more precise you

    can be, roughly. Slide 22 CC BY-SA richargh.de Dimension 2 Dimension 1 Dimension 3 The most likely location.
  14. We need a tool for this 1 free for open-source

    https://codescene.com/ 2 https://codecharta.com/ 3 Many more like this exist. This list is not complete. Slide 23 CC BY-SA richargh.de Free, open-source, all data stays local, extend with your own metrics. CodeCharta2 No €-invest to try forensics 1 powered by CodeHealth , the only validated metric measuring the business impact of code quality. Commercial
  15. CodeCharta see codecharta.com, free, open-source, all data stays local Slide

    24 CC BY-SA richargh.de Folder Depth File ex. complexity ex. Lines of code ex. churn File
  16. Slide 25 CC BY-SA richargh.de Maybe I’ll look at the

    complex code first Complex code by itself is not bad. But what about complex code that is changing all the time? Changes in complex code are much more risky and expensive.
  17. Complex code that is changing all the time See codecharta.com,

    free, open-source, all data stays local Lines of Code Cycl. Complexity Churn (high) ModuleService Lot‘s of code. Many decisions. Lot‘s of change. And, intention-hiding name Slide 26 CC BY-SA richargh.de
  18. Adress when you create the test coverage See codecharta.com, free,

    open-source, all data stays local Lines of Code Cycl. Complexity Coverage (low) Slide 27 CC BY-SA richargh.de ModuleService Lot‘s of code. Many decisions. Almost no test coverage. Still, intention-hiding name
  19. Often, not always, overlaps with Sonar/Claude smells See codecharta.com, free,

    open-source, all data stays local Lines of Code Cycl. Complexity Code Smell (high) Slide 28 CC BY-SA richargh.de BusinessModel Lot‘s of code. Many decisions. Lots of smells. Smells: FIXME comments, shotgun surgery, law of demeter, …
  20. Such maps have huge benefits over TODO lists 1. Not

    a 1D list, but three dimensions we can correlate 2. See the forest and the trees → You can see file and cluster hotspots at the same time 3. Explorable with drilldown possible, not aggregated 4. Shows the state to stakeholders and experts alike Slide 30 CC BY-SA richargh.de
  21. Graspable code, even for stakeholders See codecharta.com, free, open-source, all

    data stays local, 3D print included ☺ Slide 31 CC BY-SA richargh.de
  22. Slide 32 CC BY-SA richargh.de We improved names, added tests,

    reduced nesting and split up the remaining complexity of the hotspots. The team can work much faster now. before after
  23. Slide 34 CC BY-SA richargh.de You there You are now

    in charge of scaling Phoenix. Scaling? You mean add more people?
  24. * Yes, onboarding is much more than how the code

    looks. But we can certainly make it easier by investigating the code. Slide 35 CC BY-SA richargh.de Scaling? You mean add more people? And she is gone. What a nightmare, onboarding always takes forever*.
  25. Knowledge silos are a risk and bad for onboarding See

    codecharta.com, free, open-source, all data stays local Lines of Code Cog. Complexity Number of authors (1) Slide 36 CC BY-SA richargh.de Only one person knows about this critical code?!
  26. Invisible coupling can make onboarding rather tricky Seasoned developers have

    an intuition what parts are tricky and have to be changed together. Slide 37 CC BY-SA richargh.de
  27. C is always commited together with … 1 from the

    book https://pragprog.com/titles/atcrime/your-code-as-a-crime-scene B C A Change Coupling1 Static Coupling Mod. I Mod. II Mod. III Mod. IV D E Slide 39 CC BY-SA richargh.de
  28. * from the book https://pragprog.com/titles/atcrime/your-code-as-a-crime-scene See codecharta.com, free, open-source, all

    data stays local Lines of Code Cycl. Complexity Change Coupling (high) Ingoing Change Coupling RentComponent RentComponent Notice that no compile-time relation exists between the temporally coupled files. Slide 40 CC BY-SA richargh.de Change Coupling, the invisible coupling
  29. Change coupling starts simple 1. Often it’s a simple act

    of Copy/Paste 2. This copy has to stay in sync1 with the original lest you get bugs 3. This is a problem of duplicated knowledge2 4. Refactor towards SPOT3 (single point of truth) 1 https://connascence.io/ 2 https://verraes.net/2014/08/dry-is-about-knowledge/ 3 SPOT captures the idea better than DRY https://wiki.c2.com/?SinglePointOfTruth Slide 42 CC BY-SA richargh.de
  30. Slide 44 CC BY-SA richargh.de But the dependencies in code

    are now uncomprehensible Have you tried- Thinking? :| That seems unhelpful. I was thinking of…
  31. Which tool? 1 free for non-profit open-source https://www.hello2morrow.com/products/sonargraph/architect 2 https://github.com/MaibornWolff/dependacharta

    3 Many more exist. The list is not complete. Slide 45 CC BY-SA richargh.de Free, open-source, all data stays local, early alpha. DependaCharta2 No €-invest to try forensics swiss army knife for architects SonarGraph1 Commercial
  32. DependaCharta Find all Dependencies Hide downgoing arrows, for less noise.

    1 https://github.com/MaibornWolff/DependaCharta, free, open-source, all data stays local, early alpha Slide 46 CC BY-SA richargh.de Sort top-to-bottom heuristically Has only outgoing dependencies Has only ingoing dependencies Has more outgoing dependencies, than the one below Top Bottom MetricChooser .component MetricChooser .service import {} from “”
  33. Primary focus on the upward dependencies * The ones that

    create knots in your brain. X depends on Y but Y also depends on X. ** see https://github.com/MaibornWolff/DependaCharta, free, open-source, all data stays local, early alpha Slide 47 CC BY-SA richargh.de Upgoing Dependency
  34. Also find central/monolithic state * Hard to scale independently if

    everything depends on the same state. Slide 48 CC BY-SA richargh.de
  35. Identify file cycles Slide 49 CC BY-SA richargh.de Upgoing Dependency

    Downgoing Dependency that creates a file cycle
  36. Identify the most connected components see https://github.com/MaibornWolff/DependaCharta, free, open-source, all

    data stays local, early alpha Slide 50 CC BY-SA richargh.de Upgoing Dependency Downgoing Dependency that creates a file cycle Downgoing Dependency, only shown on hover
  37. Slide 51 CC BY-SA richargh.de We grouped things cohesively, we

    added abstractions where necessary. Everywhere? No! Only where change needed to happen.
  38. Slide 52 CC BY-SA richargh.de But then we made mistakes.

    We couldn’t keep it all in our head. Well you could define your architecture rules as code.
  39. Code forensics provide feedback cycles • Weekly/Monthly/Quarterly • Manual review

    of your Chartas • The longer the cycle, the more can get out of sync • But no one wants to look at maps daily • There is just not enough changing there • Enter automation Slide 53 CC BY-SA richargh.de
  40. Define your goal as code Example uses Dependency-Cruiser https://github.com/sverweij/dependency-cruiser TS-Arch

    is an alternative: https://github.com/ts-arch/ts-arch 1. { 2. name: 'shared-may-not-access-anything', 3. comment: 'Shared should not be dependent on anything.', 4. severity: 'error', 5. from: {path: '^src/shared/’ }, 6. to: { pathNot: ['^node_modules/’ ] } 7. } Slide 54 CC BY-SA richargh.de Define what you want (dependency-cruiser.js) 1. { 2. "type": "dependency", 3. "from": "src/shared/log/logger.ts", 4. "to": "src/features-supporting/config/config.facade.ts", 5. "rule": { 6. "severity": "error", 7. "name": "shared-may-not-access-anything" 8. } 9. } Define known exceptions (.known-violations.json) 1. "lint:architecture": " 2. npx depcruise src 3. --ignore-known 4. .known-violations.json 5. " Check continuously
  41. The manual review is still useful • Weekly/Monthly/Quarterly • See

    where issues accumulate • Notice clusters that were not there before • Discover unintended things not covered by rules • Fix existing violations on demand Slide 56 CC BY-SA richargh.de
  42. Review your violations See codecharta.com, free, open-source, all data stays

    local Lines of Code Arc. Violations Arc. Violations (high) Slide 57 CC BY-SA richargh.de
  43. Slide 58 CC BY-SA richargh.de Well we reduced complexity in

    key areas, improved test coverage, decoupled modules, - I don’t see any of that. You can see the effects in our delivery. You there Everything seems to be running smoothly. What did you do?! But I could also show you a map.
  44. Slide 61 CC BY-SA richargh.de For other teams you mean?

    No it’s very easy to get started- Hrmmmm Is it hard to get started?
  45. Slide 62 CC BY-SA richargh.de For other teams you mean?

    No it’s very easy to get started- And she is gone
  46. Get Started in one line All it takes is one

    line See https://codecharta.com/docs/overview/dockerized Slide 63 CC BY-SA richargh.de 1. docker run \ 2. -v .:/mnt/src \ 3. codecharta/codecharta-analysis \ 4. bash -c 'git config ‘\ 5. '--global ‘\ 6. '--add safe.directory /mnt/src;’\ 7. 'cd /mnt/src/;’\ 8. 'simplecc.sh ‘\ 9. 'create <your-project>'
  47. The code parser supports a lot out of the box

    See codecharta.com, free, open-source, all data stays local Slide 64 CC BY-SA richargh.de
  48. You can even import Claude reports Prompt: Which files have

    the biggest problems in this codebase? Determine this with metrics for each file. Summarize all the metrics as a score for each file. Give me a report in CSV format. The first column is the complete file path, the second column the summary score, the third column is the first metric, the fourth column the second metric and so on. Slide 66 CC BY-SA richargh.de
  49. Claude can also report in CSV 1. file_path;score;critical_security_issues;any_metric_name_possible 2. phoenix/webapp/src/constants.tsx;60.94;42;86.17

    Slide 67 CC BY-SA richargh.de Merge it 1. ccsh csvimporter phoenix.claude.csv –o phoenix.claude 2. ccsh merge \ 3. phoenix.uni.cc.json.gz \ 4. phoenix.git.cc.json.gz \ 5. phoenix.claude.cc.json.gz –o phoenix.merge 6. # open the file in the visualization 7. open https://codecharta.com/visualization/app Take the generated Csv (if to your liking)
  50. Figures CCO https://www.openpeeps.com/ Slide 68 CC BY-SA richargh.de You there

    Unicorn is not making any sense. They are getting slower and slower. You are now in charge of it. Fix it.
  51. Figures CCO https://www.openpeeps.com/ Slide 69 CC BY-SA richargh.de You there

    Unicorn is not making any sense. They are getting slower and slower. You are now in charge of it. Fix it. Sure!
  52. Figures CCO https://www.openpeeps.com/ Slide 70 CC BY-SA richargh.de And gone

    You there Unicorn is not making any sense. They are getting slower and slower. You are now in charge of it. Fix it.
  53. Investigation guide, make sure your needs are met first CC=CodeCharta

    codecharta.com DC=DependaCharta https://github.com/MaibornWolff/DependaCharta Slide 71 CC BY-SA richargh.de Question Tool Area Height Color Where does most of the work happen? CC RLoC Cycl. Complexity Churn How good is my coverage? CC RLoC Cycl. Complexity Coverage Are there knowledge silos? CC RLoC Cycl. Complexity Num Authors 1. java --version # analysis uses java 2. npm i –g codecharta-analysis Look for file or cluster hotspots Question Tool Arrows Are the dependencies understandable? DC Feedback & twisted edges Do file cylces happen DC Show only cycles
  54. In case you are interested in mapping your code 1

    codecharta.com, free, open-source, all data stays local 2 https://github.com/MaibornWolff/DependaCharta, free, open-source, all data stays local, early alpha Slide 72 CC BY-SA richargh.de Give CodeCharta1 a Give DependaCharta2 a
  55. Questions? richargh.de Richard Gross (he/him) Software Archaeology Hypermedia Modernisation Works

    for maibornwolff.de/ richargh.de richargh Slide 73 CC BY-SA richargh.de https://content.maibornwolff.de/meetings/richard-gross Drink a (virtual) coffee with me.
  56. Check coordination bottlenecks Slide 75 CC BY-SA richargh.de Lines of

    Code DataMocks.ts Lot‘s of code, but no decisions. Probably fine. Cycl. Complexity Number of authors (high) FleetService.ts Lot‘s of code, many decisions and 20 authors. Why?
  57. If you need more flexibility Easy to get started Easy

    to extend See codecharta.com, free, open-source, all data stays local Slide 76 CC BY-SA richargh.de 1. java --version # analysis uses java 2. npm i –g codecharta-analysis 3. git clone <phoenix-project> 4. ccsh unifiedparser phoenix –o phoenix.uni 5. # open the uni file in the visualization 6. # all files stay on your machine 7. open https://codecharta.com/visualization/app 1. ccsh gitlogparser repo-scan --repo-path=phoenix –o phoenix.git 2. ccsh merge phoenix.uni.cc.json.gz phoenix.git.cc.json.gz –o phoenix.merge 3. # open the merge file in the visualization 4. # all files always stay on your machine 5. open https://codecharta.com/visualization/app
  58. Add Sonar (more metrics, more languages) Add Sonar Extended language

    support: https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/languages/overview Slide 77 CC BY-SA richargh.de 1. ccsh sonarimporter <your_server> <your_project_id> -u <your_key> –o phoenix.sonar 2. ccsh merge phoenix.sonar.cc.json.gz phoenix.git.cc.json.gz –o phoenix.merge 3. # open the file in the visualization 4. open https://codecharta.com/visualization/app