
How to Become an Analytical Programmer â Solve the âRock, Paper, Scissorsâ Game 5 Ways Using JavaScript & Mermaid.js
How to Become an Analytical Programmer â Solve the âRock, Paper, Scissorsâ Game 5 Ways Using JavaScript & Mermaid.js êŽë š
Over the past year, Iâve explored tools and practices that help developers build an analytical mindset. One recurring theme is how experienced programmers often describe understanding code as forming a mental picture â a conceptual map of the programâs flow.
When it comes to software development, finding ways to visualize these mental models is a common thread. Many developers describe sketching workflows or imagining them mentally to reason through code. And in my own experience working with senior developers and software architects, this visualization habit is extremely common.
A 2013 Quora post captures this well:
âA top coder sees a program graphically (âŠ) A data structure as a hierarchy of relationships, a program as a network of data pipes⊠The first and only time he reduces pictures to words is when he writes code.â âRober Wagner
So it appears that developing our ability to recognize patterns in code could help us to develop our expertise. But programming is rarely that straightforward â there are often multiple ways to solve the same problem. It also reflects a developerâs personal habits, experiences, and styles. So which patterns matter, then?
Imagine you assign the same task to five developers: build a small game using HTML, CSS, and JavaScript. Each solution should follow the same functional rules. What are the chances their code will look the same?
Youâd expect that their implementations might differ, but the underlying mental workflow â the internal logic they follow â might be remarkably similar. If you can reconstruct this mental flow from each codebase, you can create a shared referential point for comparison. Once this conceptual diagram is in place, you can âoverlayâ it on each codebase to identify where they diverge in structure, logic, or abstraction.
Ever since I started coding, spotting âpatternsâ while comparing other peopleâs code has fascinated me. Iâve found the process of comparing code not only educational but also enjoyable.
Up until now, Iâve approached it mostly by intuition â but Iâve always felt the need for a more structured method. This article explores a more systematic approach to code comparison, reflecting on what works well and what can be improved.
How to Read this Article
This article is intentionally extensive. Instead of just showing the end result, Iâll walk you through the methodology so you can recreate or adapt it for your own code comparisons.
That said, there are different ways you might approach this article, depending on your interests:
- Just curious about the idea? The core argument is already laid out in the introduction. Maybe read the conclusion too, and that might be enough for your needs.
- Looking to improve your portfolio? Skim through the analyses. If you're working on a game project, youâll find comparisons of five JavaScript implementations of Rock, Paper, Scissors. These may give you practical ideas for your own code.
- Interested in code analysis? Read the whole thing. This article goes deeper into why analyzing code is valuable and presents a practical methodology â including tools â you can apply.
Visual Tools for Code Comparison
There are many tools and approaches for code analysis, and although there are more and more âautomaticâ ways of doing it, flow diagrams are still incredibly useful. Unfortunately, while theyâre widely used in programming education and analysis, their use for comparing different implementations is rarely discussed or illustrated in tutorials.
Still, the potential is clear. Flow diagrams capture structure and logic in a compact, readable form. They're heavily used in compiler design for analyzing control flow, optimizing logic, and identifying bugs.
When applied to comparative analysis, they can highlight differences in:
- Modularity and abstraction
- Execution flow
- Separation of concerns or unnecessary complexity
But not all diagram types are equally effective for this purpose. Traditional flowcharts often dive too deep into the nitty-gritty, repeating low-level logic like if-else branches already visible in the source. While helpful for understanding a single script, they may obscure broader design patterns when comparing multiple implementations.
When comparing codebases, a better option is to focus on code structure: how functions, modules, and scopes relate and interact. For that, system block diagrams are a better fit.
Why Use System Block Diagrams?
System block diagrams visualize a program at a higher level. They use labeled blocks to represent major components (functions, classes, modules) and arrows to show how data or control flows between them. This lets you focus on architecture: which part does what, and how do they work together?
Used for code comparison, placing two system block diagrams side by side immediately highlights structural and design differences. You can see at a glance how one solution favors modularity, another embeds logic in fewer blocks, or which one better separates concerns.
Still, system block diagrams can be drawn in different ways â some emphasizing structure, others workflow. Is there a format that combines both?
The Use Case-Driven System Block Diagram
A strong candidate is the use case-driven system block diagram. An example of this variant is suggested as part of the resources for a computer science curriculum (âAdvanced Object-Oriented Programming and Designâ COMP310) of Rice University.
Unlike use case diagrams (which focus only on actors and goals), use case-driven system block diagrams are more implementation-focused. They still show modules and data flow, but through the lens of system functionality and user-driven logic.

Interestingly, the example above effectively exemplifies its usage for evaluating existing architectures. This confirms the suitability of this type of diagram for comparisons between codebases. Simply draw one diagram per implementation, striving to find their same functional goal. Then, compare their workflows and structures side by side. Youâll quickly spot which solution is more modular, more efficient, or easier to maintain.
What We Are Going to Do
To elaborate upon the suitability of this methodology for code analysis, weâll apply the fundamentals of use case-driven system block diagram methodology to analyze five JavaScript projectsâ code â each created by a different developer â implementing the Rock, Paper, Scissors game on CodePen.
The Rock, Paper, Scissors (RPS) game is a simple two-player challenge where each participant simultaneously shows either a ârockâ, a âpaperâ, or âscissorsâ depicted by one of their hands, usually after a countdown. Then they apply the following rule to decide the âwinnerâ:

- Rock beats scissors
- Scissors beats paper
- Paper beats rock
If both players choose the same option, itâs a tie.
In most programming versions, the player faces off against the computer, which makes random (or pseudo-random) choices. Itâs a favorite beginnerâs project because itâs easy to understand and fun to build.
The Code Examples
We are going to compare the (vanilla) JavaScript code for the following 5 projects, ordered by complexity:
- âCPC Rock Paper Scissorsâ by Amit (
@ghaste
in CodePen) - âRock Paper Scissor game using native drag & dropâ by Hmz C (
@HmZ2
in CodePen) - âRock Paper Scissorsâ by Brad Traversy (
@bradtraversy
in CodePen) - âRock Paper Scissors OOPâ by Damian (
@CvtS
in CodePen) - âRecurrent Neural Network - Rock, Paper, Scissorsâ by Andrew Worscerter (
@amwmedia
in CodePen)
In order to keep the article shorter, the full code wonât be provided here, except for some exceptional cases. You are encouraged to visit the corresponding projects in CodePen to have a look at the code alongside the analysis. Because the authors can update or even delete the code in CodePen at any time, Iâll also add links to Gists with the code I analyzed at the time I wrote the article.
Follow this link
if you want to find the copy of the JavaScript codes used for this article.
How to Choose Your Projects
To find the projects, I searched CodePen for any pen about âRock Paper Scissorsâ. Then I checked out the edits of some of them, and chose the ones I found the most interesting. I made a point to choose ones with varying complexities.

The Scope
First of all, our goal here isnât to judge the quality of the codebases. Instead, itâs to demonstrate how we can use this diagram-based methodology to compare them.
CodePen projects often include quick demos, experiments, or even AI-generated snippets. Some developers might be more interested in the HTML/CSS of the project. But while they donât always follow best practices, thatâs what makes this exercise interesting â the diversity of approaches reveals valuable contrasts worth analyzing.
The Methodology
For the comparison, weâre using a methodology inspired by Rice Universityâs COMP310 course, which suggests the following high-level steps for constructing use case-driven system block diagrams:
- Add all system use cases to a single diagram. These use cases will be similar to âsteps in a workflowâ.
- Group related cases within conceptually â or functionally â related operations.
- Encapsulate groups into modules (or blocks) based on roles and responsibilities. Start drawing the relationships (note: what we should understand for encapsulation here shouldnât be confused with other definitions like the one given in OOP).
- Decouple operations as much as possible â refine scope and minimize interconnections.
In order to allow the comparison between code examples, we will try to find cases (or steps), modules, and relations that are consistently similar between each code example, independently of the âarchitectureâ.
Although UML compliance is encouraged in the original course, weâll take a lighter approach â preserving the intent and structure without strictly following every UML rule.
How Weâll Build the Diagrams
The Rice course focuses more on what the diagram should show, but not so much on how to actually build it. For that, I refer to a previous article where I broke down the diagram creation process. Hereâs how the two approaches align:
Step (from earlier article) | Corresponds to (Rice methodology) |
---|---|
Define a scope | Identify the goal and context for your diagram |
Find the start and end of the workflow | Identify use cases (actually, a general scanning of the workflow) |
Identify deep-dive vs. generalized sections | Identify groups of cases. Prepare for modular encapsulation |
Iterative refining and generalization | Applied throughout to improve module clarity and decoupling |
Enhance and extend | Equivalent to fine-tuning and breaking dependencies |
Feel free to revisit that article if you want a more detailed walkthrough of these steps.
Our Tool: Mermaid.js
To create the diagrams, weâll use Mermaid.js, a JavaScript library that converts text into diagrams. Itâs Markdown-compatible, which makes it especially handy for online projects, blog posts, and documentation.
The main reason I chose Mermaid.js is that diagrams are easily editable, so we can:
- Focus on defining relationships instead of worrying about layout
- Easily iterate and update as we discover more structure in the code
- Allows code reusability
Mermaid.js is also highly configurable, allowing a certain level of customization. It was also made for the web, so itâs compatible with JavaScript, CSS and Markdown. But itâs not a perfect tool, and its use poses challenges both because of the limitations of the tool itself and even because of the limitations of using visual diagrams for code analysis.
If you arenât familiar with using Mermaid.js, I wrote an extensive tutorial about the tool, along with its pros and cons. Although I will refrain from talking in-depth about Mermaid.js here, I will make use of some other tricks that were not included in previous articles.
Be aware that to keep consistency in sizing and titling all resulting diagrams were subjected to post-treatment, which also included color filtering to improve contrast.
Five Code Examples of Rock, Paper, Scissors
Final Thoughts
As a developer, you will be exposed to many different lines of creative code yourself. Or how Robert C. Martin pointed it out in his book âClean Codeâ:
âIndeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code.â
So, learning to understand other peopleâs code is an essential skill that every programmer should develop. And this learning only happens by studying other peopleâs code and trying to reveal their tricks and bugs.
That is why finding good ways to reveal patterns when comparing code is so important. And that has been the main purpose of this project.
When I started, I still wasnât sure about what to expect from the approach. Let me share with you what I learned.
What I found limiting from this approach was:
- The more complex the code, the more complex the diagram gets, making it difficult to read. And the more difficult the diagram, the more difficult is to work out a diagram with Mermaid.js. You will also have to make more definitions, add more color, use more tricks, and so on in order to seek clarity. And the more âsolutionsâ you have to find to clarify your diagram, the higher the risk of making it less clear.
- It takes time and practice. This kind of technique is not something that you learn all at once. You might find yourself making a lot of changes before getting the ârightâ result. If you are doing this with Mermaid.js or any other scripting tool, you will have to learn to script with them, too.
- This approach is not about visualizing algorithms or syntax. I suspect that if you read the analyses of this article with no knowledge about machine learning or object-oriented programming, this analysis likely didnât teach you how to do machine learning or OOP. To understand those projects you have to already have internalized the âpatternsâ on how to do either OOP or machine learning, or be in the right moment of your learning curve, in order to be able to extract something from the code.
What I found beneficial from this approach:
- Something that I learned the hard way was that good programming is not only about algorithms and syntax: it is also about structure and organization. And this approach will give you a lot of information about that.
- It helps you break the code apart into functional operations. You adopt a âdivide and conquerâ approach to studying code.
- Even if you are not visualizing the algorithms, you learn algorithms. Why? Because the approach forces you to understand the code. In order to find those functional operations, you will find yourself forced to study what some sections of the code are doing. So you will have to study more code.
- You learn by comparison. That is an interesting by-product: once you have found different implementations for a similar functional operation, you learn by their differences. The diagrams will then guide you to the sections of the code that are solving that specific problem you are interested in and youâll be able to compare it within the context of a larger codebase.
- The diagrams acts as mnemotechnical artifacts to remember pieces of code. You can use those diagrams to recall a piece of code that was interesting to you, and then youâll be able to find it more easily than by having to go through the whole code again.
What I found more interesting about this approach is the numerous questions that came to my mind during and after doing the analyses:
- Why did the author follow this approach?
- What drove their decisions?
- How could I better organize it if I worked on it?
- Which techniques would I like to combine?
- What should I avoid for this project?
And so on.
Another effect was the feeling that I could now easily recognize the same âtemplateâ in other projects without having to make the diagrams. It starts to be more natural.
If you feel you want to implement this approach next time you come across several codebases you want to compare, I recommend you do the following:
- Donât stick only to visuals. Combine this with other tools. This is just one part of the whole process. For example, use AI to get a textual description of the code and use the diagrams to visualize the flow.
- Always go to the code as it is the âsource of truthâ. You (or AI, if youâre using it) might have gotten it wrong at certain points, so always check.
- Better to compare code examples that are at your level or just a bit higher, and be prepared to challenge yourself by studying new concepts. For example, if you have just the fundamentals of OOP clear in your head but you havenât started to work on it, find simple examples at your current level and a few more made in OOP that solve similar problems and compare the approaches. I ensure you that you will start finding the patterns.
- Come up with questions. The analysis might reveal structures and workflows and help you get into new programming techniques, but it wonât tell you if those structures or techniques were the ârightâ solution. You have to investigate more from that point. Then you can compare theory with practice. And then you will come up with more questions!
- Select projects that are not subject to change.
- Donât worry about how old the projects are. Syntax is not what you are looking to learn from this analysis. It is code structure, organization, and logic. The âmap in the mind of the developerâ.
- Keep it real. If your goal is to learn to code and your time is limited, bear in mind that this kind of analyses will take extra time. It wonât result in concrete code either. It might be good planning for analyzing new codebases at a high level of generalization. But even if itâs too general, I assure you that the time you devote to it will be worthy.