<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Allan Kong on Medium]]></title>
        <description><![CDATA[Stories by Allan Kong on Medium]]></description>
        <link>https://medium.com/@allankong?source=rss-8d916fe51be8------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*7rx1i88rnhXd1MlFoYICcQ.png</url>
            <title>Stories by Allan Kong on Medium</title>
            <link>https://medium.com/@allankong?source=rss-8d916fe51be8------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 23 Jun 2026 06:36:01 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@allankong/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Communication Required — The Social Myth of Software Engineering]]></title>
            <link>https://medium.com/@allankong/communication-required-the-social-myth-of-software-engineering-7d28c64fbb6c?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/7d28c64fbb6c</guid>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Wed, 11 Feb 2026 14:46:01 GMT</pubDate>
            <atom:updated>2026-02-11T14:46:01.040Z</atom:updated>
            <content:encoded><![CDATA[<p>Now, this article is primarily aimed at younger readers, but it is intended for everyone. Most people who reach a senior or higher level understand how important it is to be amiable, friendly, and overall adept at social relations. However, I also had my fair share of seniors and architects who were easily irritated and excited to say the least. So, not everyone fully follows that to their heart.</p><p>Ironically, we commonly think of computer scientists or engineers as hermits. They are stereotypically tech dorks — who could be geniuses — but are unable to communicate with anyone. I believe that this stereotype is detrimental to one’s personal perspective on their role as a software engineer. I’ve decided to write a blog post discussing why it’s beneficial to diversify your knowledge and explore various avenues of life.</p><p>My argument today is that communication is the primary metric for a good engineer, with engineering skills as a secondary metric. I am not suggesting that technical skills are obsolete; instead, I would prefer an engineer with weaker technical skills and greater communication abilities than vice versa.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/495/1*eBUgwIziMQoOfpDYlMxg7Q.png" /><figcaption>Software is an introspective process</figcaption></figure><h3>Motivation</h3><p>I’ve started to find a bit less interest in software engineering as of late, and have turned toward other new hobbies and interests. I still find software enjoyable and exhilarating. Instead, I’ve been focusing on engineering through the communication and interpersonal side. I’ve noticed two major things that shifted my mindset.</p><p>The first of which is that recruiters stop caring about technical skills at a certain point, more for seniors than juniors. What really makes people stand out, after a certain technical skill level, is the ability to mesh well with the rest of the company. Recruiters genuinely care about the people they hire. False positives from personality are more tiresome than false positives from a skill difference; the latter can be trained.</p><p>Secondly, you can learn a lot more about software engineering by exploring other ways of thinking. I consider engineering to be more than just the solving of technical problems, but the mindsets we use to navigate them. This includes the understanding of social context, communication, and independence. We can improve these contextual skills through the exploration of anything. I mean anything. Here is an example. Dance lessons have taught me about the importance of being more assertive. As a leader, I was called a “gentle soul” since I gave weak pushes and pulls to my followers. This is dangerous as it is harder to tell where my intentions lie, and could result in a misstep and injury. Being assertive — not forceful — is an important aspect of life.</p><h3>The Origin of Lack of Socialization</h3><p>The problem is that people generally place less emphasis on the collaborative side of programming. It has become about technical skills. I will be using one of the most social majors as a comparison throughout the article: business students.</p><p>One example that illustrates the contrast between software and business majors, besides the fact that we are constantly staring at a screen, is that business students typically have a hobby section in their resumes. However, as software engineers, we would have a skills list in place of that.</p><p>Our disregard for social skills did not come out of nowhere but was socially built over time. One such explanation for this is that much of our schooling for software engineering is very individualistic. University classes predominantly focus on individual projects. This makes sense for many classes and class structures. If we are trying to teach complex ideas — such as databases, networks, and security — it would be most effective to have individuals work by themselves. However, the consequences are that we have far fewer opportunities to interact with peers, which is a mismatch with what the industry expects. This is not the fault of the school entirely, whose goal is to teach concepts to its students, and not necessarily prepare them for the real world.</p><p>Then, there is a cultural misunderstanding of what a computer scientist is and what a software engineer is. Many computer science students transition to software engineering roles. This is quite odd because computer science is about math, logic, and the theory of computing. There are usually very few classes that teach skills that are used in industry, even on the programming side. Forgetting about the technical side, there are typically no classes dedicated to working in teams, social environments, or anything in the industry. Again, this is not the fault of the schools; they are teaching the subject — computer science — as they should. But this simply results in a world where we have normalized people having the wrong set of skills for a job, then being shoehorned in later. Or this requires individuals to develop the required skills outside of their education and studies.</p><p>Outside of school, commonly, we work on software projects. Again, this is done on an individual level. It is very rare for both seniors and juniors to be collaborating with others on a software project. We push code alone; we read code alone and never document anything. Even if you did document code, it is hard to reach the same level of collaboration, as it’s not the real thing. In fact, it’s very hard to get the real thing: communication in a business setting. I think the best we can do, as developers, is to contribute to open-source software. But, even then, it is very difficult to do for many, and it can be more well-defined.</p><p>All of this is enhanced by the cultural aspect of software geeks. We are traditionally represented as very socially awkward, isolated people; the list goes on. This would naturally delve into our own subconscious; we begin to associate our traits with our character. Naturally, one could follow the line of conformism. We think that as software geeks, it’s fine not talk to people. We could also use it as an excuse to avoid uncomfortable situations, to justify not getting out of our comfort zones.</p><p>I think we should start rethinking the detrimental harm that this is causing us. Then, start understanding why it’s so important for us to explore ourselves and the social world.</p><h3>The Need for Human Skills</h3><p>So, why do I care so much about these communication skills anyhow? This is where the bulk of the article is heading.</p><p>Unlike what we are taught in school, ambiguity exists, and it requires communication to solve. We are constantly given specific problems to solve within our academic career. Especially us computer scientists; we solve discrete and well-defined problems. That is hardly ever the case in the real world.</p><p>Every single technical problem we solve requires some level of collaboration. Here is one basic example. If we are committing to the codebase, we need to do pull requests. There are times when people can give off the wrong impression in code reviews. They could come off as a narcissist, unhelpful, or just a brat. It’s a simple example, I know, but if you don’t address these problems, some people would be indirectly labeled as bad code reviewers — then eventually completely ignored. Every stage of problem-solving — in a team — requires team communication. You need to check what other people are thinking. You need to be assertive, like in partner dancing, to prevent dangerous injuries in the future. Communication does not only involve meetings, but there is also writing code that follows the conventions of others and understanding other people’s priorities. There is also the collaboration with the business itself. The needs of the business are changing and context-dependent. In a startup culture, people care more about going fast and breaking things. Before doing any programming, you should understand the business impact and purpose of the things you do. You could think to yourself: “How will what I do help the team and the company?” This line of questioning is not a technical skill; this requires empathy — a social skill.</p><p>Let’s say you were working alone — no team at all! Okay, there must be no need for social skills anymore, right? Well, I disagree. I think that ambiguity in business will always exist. Therefore, business objectives are never defined precisely. Allow me to elaborate. Let’s say you were working for the CEO, and he wanted a certain set of features for the latest web app: the ability to edit the user’s birthday on the profile page. Okay, that sounds simple. What kinds of ambiguities could possibly exist? Well, do you want verification with a government body to ensure that the birthday is valid? Do you want to send a confirmation email with the change? Do you want this to be a change that can only be done once or repeatedly? There can be infinitely more questions; it is a matter of imagination. Because businesses can never be defined to the smallest details, there will always exist these ambiguities. Some of these questions are valid; some of these could be a waste of time. How can we differentiate between them? Well, there comes the aspect of empathy and communication. We need to align the company goals with the business. This is even more so the case if you were a startup founder, where you also need to take on the role of the CEO. To develop a meaningful product, you require the ability to communicate with the higher business managers or customers. As stated before, this is to empathize with the business.</p><p>Let’s say that you were working a role where tasks with specialized and specific conditions were handed to you. I know people who work — predominantly in the low-level programming field — where the tasks they are given are very well-defined. An example would be to optimize a matrix multiplication algorithm. In this case, I want to argue that autonomy is cooperative. If we are truly autonomous, it means that the work has been done for us before by a higher level of business. This higher level discussed the business goals, how to achieve them, and assigned tasks to the lower level. It has been distributed and then well-defined. It typically requires that the person distributing the tasks is an engineer themselves. Otherwise, ambiguity would exist again. Then, you are handed these requirements and then must implement them — this role can be called a code monkey. It can be the case that some companies would prefer this structure. But there are two arguments to make against this. These code-monkey roles are the most replaceable by the looming threat of AI, since it is simply cheaper. Therefore, we could start considering code-monkey roles no longer viable for the future of engineering. Another is that, typically, juniors would face a more automated workload, but the goal is to wean them into a more leadership role. After understanding all the technical intricacies, you would be expected to hold more social responsibility. Unless you want to remain in the same spot in your career forever, you need to take on social responsibility.</p><p>In the end, it is vital that you have great social skills. Engineering — misunderstood to be an isolated role — is one that demands constant communication with others. To succeed and level up in any organization, you must focus and hone your communication skills.</p><h3>Call to Action</h3><p>How do we improve our social skills, from communication to empathy?</p><p>I think there are two simple things to try:</p><p>1) Getting involved in media. 2) Trying out new things.</p><p>Media shows us different worlds. It offers us a unique perspective on our worldviews. Films, books, and music are powerful because they show conventions of what the world is like, but also offer different ideas of what it could be. They allow us to change our ways of thinking. When watching films, we can see various conflicts arise and gain emotional intelligence as we follow the characters’ struggles. Better yet, try writing. Try writing blogs, diary entries, or even poetry. I find it a brilliant and introspective process that helps me understand both myself and the world better.</p><p>Then, try out new things. This is usually best in a group setting. If you are in university, please go and try out new clubs. It is a very exciting feeling to learn new things with others. It allows you to see their perspectives on the world and how they can integrate with your own. One example is trying out the improv club. I can tell you that the people there have a very bold and unique process for problem-solving. They are on the spot and dynamically change ideas on the fly. It is an amazing process to see different worlds and apply it to myself. There is also the social aspect of getting used to just talking to people. By joining clubs, you get used to having to talk with people often. It builds social skills.</p><h3>Conclusion</h3><p>Well, I hope you understand the importance of honing your communication abilities — and I’ve convinced you to start trying out some new hobbies. It took me a while to realize, but life is so much more than just programming. You never know how much joy you can find by putting yourself out there.</p><p>Thanks for reading and have a wonderful day!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d28c64fbb6c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Year in the Making: 6 Lessons from Building ComputerScienceResources.com]]></title>
            <link>https://medium.com/@allankong/a-year-in-the-making-6-lessons-from-building-computerscienceresources-com-47006c404866?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/47006c404866</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[entrepreneurship]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[side-project]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Mon, 22 Dec 2025 18:20:43 GMT</pubDate>
            <atom:updated>2025-12-22T18:23:29.863Z</atom:updated>
            <content:encoded><![CDATA[<h3>Introduction</h3><p>I know my loyal fans are questioning why I have not written a blog post in such a long time. But I have finally returned with wisdom after a busy semester of school. To those who are new to my content, I hope you enjoy this read!</p><p>Recently, I’ve been working on a side project called <a href="https://computerscienceresources.com.">https://computerscienceresources.com.</a> I’ve noticed that there is no centralized location for the diverse range of computer science resources. I see a multitude of ways to break into various software fields, but these resources are scattered all over the place and sometimes generally hidden. Furthermore, I sometimes hear a lot about some resources, like Brilliant, from all these YouTubers. And, as a skeptic, I want to know how good or bad the resource is: the teaching quality and engagement. Then, there is another issue of people asking me what resources I should recommend for getting into software.</p><p>These three issues:</p><ul><li>Wanting to find more ways to learn software</li><li>Determining the quality of a resource, like a bootcamp</li><li>Sharing learning methods with others</li></ul><p>And the lack of a centralized website has led me to develop <a href="https://computerscienceresources.com">https://computerscienceresources.com</a>.</p><p>But today is not about promoting my site. I have been developing this site for well over a year now. I’ve made numerous mistakes since the beginning. I think that some lessons can only be learned from developing a long-term project, as this was my first project that was not just a throwaway toy project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/492/1*H5r6hUdgAWHgKcHxHlhftQ.png" /><figcaption>Sometimes releasing a project feels like fighting the entire world</figcaption></figure><p>Enough chit chat. I’ll start with the lessons.</p><h3>Understanding the Consequences of Your Tech Stack</h3><p>After reviewing various options for my tech stack, I chose Laravel because it places a strong emphasis on developer friendliness, boasts a robust ecosystem, and is a mature MVC framework.</p><p>I did investigate other options like Supabase, Phoenix with Elixir, Node.js, and the .NET framework. However, Laravel’s ecosystem seemed much stronger for the kind of work that I wanted to get done.</p><p>However, you must also understand that some frameworks are less “sexy” than others. When you limit yourself to a tech stack like Laravel, where the language is PHP, you may get fewer job opportunities than with a more popular one. Even if you end up creating a less robust application, recruiters like seeing popular frameworks like Node.js on your resume. I’ve had several interviewers question why I am using PHP in 2025. No doubt that if I chose a web framework like Spring Boot, Django, or ASP.NET Core, which uses more popular languages, interviewers would be more impressed.</p><p>But I don’t think that the language mattered much to me. I was more focused on getting my application published. I knew that coming in, the flashiness of the language was not important. With the scaffolding that Laravel provided, I was able to get a prototype up and running and develop my application with great speed, as Laravel provides a very nice starter kit (<a href="https://jetstream.laravel.com/introduction.html">https://jetstream.laravel.com/introduction.html</a>). More importantly, I think the architectural decisions and software skills I’ve learned from this project apply to software development holistically. In this case, I’ve become very proficient with the MVC pattern.</p><p>The lesson to learn here is that recruiters don’t understand that one can become proficient with a framework by only having worked with similar ones. I’m certain I could pick up Django without much difficulty now (having done Laravel) — but to a job recruiter, they don’t see that.</p><p>No matter what framework you choose, understand what you want to achieve with your project: practicality or flashiness.</p><h3>Understand Your Core Features Early</h3><p>If you are going to work on this project for a long time, define what the MVP would look like. It is common advice to work on an MVP for a project and to have a list of minimum features that your application would contain. I’m not going to explain all that; I know my audience is smart.</p><p>So, I created a list of top features and split them into vital features of the application and “nice-to-haves.” Of course, for a site with resources, I had posting and filtering resources as a top priority. Then, I trimmed the core features into a smaller subset of features to create the smallest possible core feature set:</p><ul><li>Resource</li><li>Posting Resources</li><li>Editing Resources</li><li>Filtering Resources</li><li>Upvoting Resources</li><li>Reviews</li><li>Comment system</li></ul><p>What I made a mistake in was not understanding the effort that each feature was going to take. I had some features in creating a resource be very important, such as having a multistep form save to local storage. However, I focused too hard on it during the beginning, thinking it was a trivial task — originally done with jQuery. I focused so hard on this feature to even work nicely with so many different web components and inputs that I could barely even have the MVP’s core features met. What ended up happening was I spent a few months on a prototype with Laravel and Blade, with terrible code, and not even all the core features completed.</p><p>Some features were much more complex than initially expected. One of them, which I will dedicate an entire technical article to later, was creating a nested comment system like Reddit. I managed to create one in-house, but it ended up not being a core feature at all. I could’ve saved a couple of months and launched the app early. In the end, I rewrote my Laravel Blade application with Laravel Inertia with a much more advanced and wise point of view. I saw how my past setbacks had transformed into mature lessons, which resulted in scalable, maintainable, and consistent code.</p><p>The biggest lesson was not just to predict my core features better but also to realize that I could spend the first few weeks of creating an application with a prototype mindset. If I had dedicated the first phase of the application to experimenting with the features and gauging the risk and reward of certain features for myself, it would have allowed me to mess around with different major architectures without worrying about trashing the codebase, as it would get thrown out anyhow. I could’ve scheduled the delivery of my application at least twice as fast. It may seem counterintuitive to not jump straight into a project, but if I ever start a serious project again, creating a scrap prototypical project would be my go-to move.</p><h3>Overengineering Is Real</h3><p>This mistake is quite similar to the previous one, but the lesson is a little different, so I will keep it. One of the biggest things engineers love to do is optimize their code, whether that be beautiful, elegant, or fast code.</p><p>There were several times where I thought I had the best way to write my code, realized that I was following a bad practice, and rewrote my code into a cleaner format. One example was I rewrote all of my tests to a helper function method, mentioned here (<a href="https://medium.com/@allankong/laravel-randomized-form-testing-trick-eb88247ba1ce">https://medium.com/@allankong/laravel-randomized-form-testing-trick-eb88247ba1ce</a>). Afterwards, I discovered a better way to write the form tests with a package (<a href="https://github.com/worksome/request-factories">https://github.com/worksome/request-factories</a>).</p><p>Another time I overengineered was writing my comment system in such a way that I could handle 2000+ comments easily and prevented any sort of N+1 query problems. However, even now, I barely have any comments on the application. Plus, I thought of more ways that I could improve the comment system. So, software is always evolving, and it is important to have your focus on the things that will have a business impact.</p><p>The lesson is to understand that you don’t need to have your codebase, features, or anything in your product fully fleshed out. No one notices cut corners. What really makes your application stand out is the core ideas and features it delivers. So, focus on delivering that and start polishing once you have users or feedback.</p><p>Sometimes, I hold weekly recaps where I recognize things that I’ve done well and processes that I spent too much time on, even though I am a solo developer. I’ve noticed I started implementing many agile practices into my passion project, such as retros, postmortems, and sprint planning for the week. In the end, use whatever system you need to get insight on whether you are engineering the right amount.</p><h3>Trying Too Hard to Validate Your Ideas</h3><p>There are two schools of thought when it comes to validating your idea: create it and find out, or ask people and hear feedback. I think validation of the former is just more efficient for these sorts of passion projects. I feel that I should’ve spent less time determining if it was worthwhile for me to build this project to help others. I asked my friends around, and they had positive responses. Despite that, I still felt hesitant to work on this project.</p><p>What I forgot was that I wanted to work on the project for myself. Even if no one else wanted to use the site to discover learning resources, I would still use this site. I can share quality resources that I use with the world. If I think the idea is valid for myself, then it is plenty valid for others.</p><p>It may not be the best way to handle validity, but you cannot find any sort of closure in your ideas from others unless you believe in it yourself. It’s like a marriage. It doesn’t matter if your girl is the prettiest on the block; if you don’t love her, the marriage will fail. And if you love her and no one else does, it doesn’t matter. The marriage will still succeed. I didn’t need to waste so much time contemplating if I made the right decision. Now, I just continue doing this for me.</p><h3>Don’t Make It a Job</h3><p>During the development of the site, I’ve faced burnout maybe 3 times. I realized that I started treating some of the side project like a job. There came a point where I had to write tests to make development faster. However, creating a large module for the codebase sometimes resulted in an entire week dedicated to writing tests for it. This was an absolute dread that killed a lot of motivation for the project. I sometimes forget that I am working on the computerscienceresources.com project for my personal enjoyment and don’t need to force myself into torment.</p><p>Realize when you are slowing down and starting to find processes mundane. I think that ThePrimeagen has great advice about burnout (<a href="https://www.youtube.com/watch?v=KEWV5yaj_2o">https://www.youtube.com/watch?v=KEWV5yaj_2o</a>): it’s when you start finding no joy in the work you do. To follow his advice, I’ve started balancing the work with experimental fun work alongside the mandatory tedious things.</p><p>In addition, just switching work occasionally can spark more inspiration and interest again. I don’t find unit testing, writing UI, or even debugging problems boring. But if I were to spend more than a few days on one problem, I would burn out real fast.</p><p>So, stop motivating yourself by forcing yourself to get things done. That is being motivated by fear, focusing on the negative, which results in burnout. Instead, focus on the cool things that make software engineering fun and awesome. Focus on the positive side of completion, which results in fulfilling work. Experiment and swap around what you work on; then, naturally, you would discover your speed will increase as well.</p><h3>Be Proud of What You Make</h3><p>The biggest problem I’ve had and am still struggling with is being boldly proud and public with what I’ve built. Engineers see the holes in their designs, the faults, and all the problems that don’t matter and are never seen by end users. But none of that matters.</p><p>All big companies have released janky products. They proudly release their project, get feedback from their first customers, and continuously iterate from there. People release garbage all the time and slowly churn it into a mature product.</p><p>I had much fear in being public with my site. I was worried about what other people would think and the criticisms I would face. However, it’s been a few months since I’ve released the application without any advertising, not even much amongst my friends. The site has driven little traffic, which is to be expected.</p><p>So, I have reached my goal: I have not received any criticisms of the site, as I have no one to receive criticisms from. But my goal is to help many people, not build this project in isolation. I’ve started the process of publicity with this article. There is a lot of good advice in this article (<a href="https://dev.to/wasp/how-i-promoted-my-open-source-repo-to-6k-stars-in-6-months-3li9">https://dev.to/wasp/how-i-promoted-my-open-source-repo-to-6k-stars-in-6-months-3li9</a>) that I am going to follow, such as publishing on popular sites like Product Hunt.</p><p>People proudly release and market stupid and foul projects all the time. Some people have no shame and spam their awful project on Reddit and Discord. If I — with a potentially good project — don’t even try to promote it out of introversion, how do I even stand a chance against all the newly released applications? Promotion is not a commodity; it is necessary.</p><h3>Now Go Be Awesome!</h3><p>So, I hope that everyone can learn from the mistakes that I have made through the development of my site. Of course, some lessons can only be learned from doing these things yourself. But I know that if you have read through to the end of this article, then you are already a person with great wisdom.</p><p>I hope you have the best of luck with your side projects, and if you have any advice or tips for me for promoting side projects, or mistakes that you’ve made, please share them in the comments. I’d love a discussion!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=47006c404866" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What does a Merge Request Approval Entail? The Unwritten Etiquette]]></title>
            <link>https://medium.com/@allankong/what-does-a-merge-request-approval-entail-the-unwritten-etiquette-6cbf395f8f4b?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/6cbf395f8f4b</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[pull-request]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[code-review]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Sat, 05 Jul 2025 17:34:53 GMT</pubDate>
            <atom:updated>2025-07-05T17:34:53.311Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Introduction</strong></h3><p>You go to a new company and submit your first pull request. After an hour, you have a bunch of comments. Easy (I hope) — you resolve them and repeat this review cycle until you get approval. Amazing, so that was a successful PR!</p><p>Imagine the next week arrives and you request a review for another PR. Without comments, it gets approved an hour after the request. What does this mean? Did they actually review it? If so, how thoroughly did they even review it?</p><p>The answer: There is no way to know without having a standardized merge request system within the team. Or you could memorize how everyone you work with handles their peer reviews and base your feedback off that telekinetic connection you have with your colleagues.</p><p>I read this nice book on PRs, and I would recommend you do so too even if you have been in the industry for a while: <a href="https://github.com/scastiel/book-pr">https://github.com/scastiel/book-pr</a>. It helped me pick up on some social expectations and psychology around PRs that I’d never noticed before. I think this is a great book, but I think it’s missing a chapter on the ambiguous nature of merge approvals.</p><p>In the industry, there is an invisible set of guidelines when it comes to PR approvals, but it’s also expected that everyone knows what they are. So today we will discuss the implications of merge approvals, how much effort a review approval typically involves, and the expectations of etiquette.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/807/1*HOhDivl3TxDBpMKHa0zylA.png" /></figure><h3>The Levels of Review</h3><p>First, we will discuss some background information before we jump into what a merge request entails.</p><p>There are generally three levels of code reviews, with each level requiring more effort from the code reviewer. It is rare for people to always perform all three levels of code reviews. Furthermore, not all pull requests are equal, so some changes can be so trivial that they do not warrant much effort.</p><h4>The Human Linter</h4><p>This level is the most basic of them all. The reviewer does not need to even know what the code is doing. For all they care at this stage, the code could be broken, but at least it looks and sounds nice. While most companies have a CI/CD pipeline or job to help with language linting and type checking, this stage is more about the opinionated side of design.</p><p>Your codebase might have a preferred style of writing code. For instance, perhaps you are writing TypeScript, and your team decides to use arrow functions over regular functions — and to use regular functions for returning object literals. Another example is a variable that could be more descriptive: instead of writing money_for_repayment, you could do cad_dollars_for_repayment.</p><p>Another way to describe this stage is finding nitpicks with the code at a superficial level. The reviewer does not need to open a code editor and checkout your branch. This stage is predominantly done in the GitLab/GitHub merge request page.</p><p>If you don’t already know, many people will prefix comments with “nit” to indicate that they have a small nitpick with the code.</p><p>An important thing to consider about this stage is that nitpicks can be contested, obviously in a polite manner. Not every suggested edit needs to be made.</p><h4>Bug Catching</h4><p>In this stage, the logic of your code is questioned. There must be some understanding of the code, and even a high-level understanding of what is going on in the code. However, the full picture does not necessarily have to be in mind at this stage.</p><p>Ideally, if the merge request were complex, the reviewer would checkout the branch to better navigate the code and how it affects its surroundings.</p><p>This level would also involve looking at the appropriate tests and ensuring that the test conditions are meaningful (avoiding confirmation bias).</p><h4>Architecture Designs</h4><p>This level requires that the reviewer understand the intent of the code, what problem it is trying to solve, and consider how to redesign the code in a ‘cleaner’ manner, whatever that means to your team. Additional context is needed, such as reviewing the original ticket and/or some internal documentation.</p><p>The reviewer cares less about the lines of code which you have submitted in the PR, but rather the intention behind your functions, context of the codebase, and the overall designs.</p><p>This kind of review is very difficult to pull off and is mainly reserved for PRs which have major impact on customers or will be maintained for a long time. These reviews are especially difficult because reviewing systems requires a large context window and a vivid imagination. Very rarely can you, as a reviewer, try to rebuild the pull request yourself and create the designs the way you intend. I know some people have trouble imagining clean code in their mind but have no trouble writing it out. Hence, the reviewer needs to already have good context of the codebase and be able to experiment with different ideas and designs in their minds.</p><h4>Level Zero Reviews</h4><p>There is also a hidden level outside the typical three. In this case, the reviewer completely trusts you and doesn’t care about the other levels at all. Think of it as: “I can’t be bothered.” It is quite rare to get this kind of approval, usually reserved for version updates. It could be for people who don’t really care much about giving a review, are overwhelmed, or just trust the person completely.</p><h3>The Review Complexity Matrix</h3><p>The best way to know how complex your code reviews should be is to look for any documents describing how your company’s code review process works. If there is no such document, ask the engineers around and make one yourself — it will show good initiative.</p><p>But, despite the ambiguity in code reviews, there are some general implied rules for how much effort goes into the type of pull request that is made. Most teams subconsciously follow a pattern based on PR complexity and risk:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/787/1*55WFcSqPc5f6240zRR_R8g.png" /></figure><h4>Accounting for Variable Review Speeds</h4><p>The matrix above is not always accurate as companies can have variations in how they perform code reviews. Sometimes, a review that would take 30 minutes at one company would take 10 at another. However, there are some other things that can change the speed at which a person will look at your review:</p><p><strong>PR size:</strong> A bigger file, while not necessarily more complex, will require more time to review.</p><p><strong>Files touched:</strong> Changes to core modules get Architecture-level scrutiny.</p><p><strong>Author experience:</strong> Junior developers typically receive more thorough Bug Catching reviews (don’t take it personally!).</p><p><strong>Timeline pressure:</strong> Tight deadlines unfortunately often reduce review depth.</p><p><strong>Recent production issues:</strong> Teams become more cautious after bugs slip through.</p><p><strong>People aspect:</strong> People have different review speeds, or just forget about your PR midway through, and get back to it later.</p><p>Approvals are never consistent — don’t expect that people will review your pull request at an ideal speed.</p><p>Even though code reviews are inconsistent in speed, there does exist a boundary where the speed is considered too fast. The table for that would look something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/904/1*QrG8eZ0k3zHFoOTbfKZ1xA.png" /></figure><h3>The Unspoken Reviewer Personas</h3><p>Now that we have discussed the different types of speeds and the different levels of reviews, there remains the most important part of merge approvals: the person giving them. People are dynamic; each have their own biases, quirks, and patterns.</p><p>I have noticed that some people have a recognizable pattern to the way they review. Learning to identify these “reviewer personas” can help you better interpret feedback and set appropriate expectations for your PRs. These are somewhat satirical characterizations, but they reflect real tendencies you’ll encounter in most development teams.</p><p><strong>The Nitpicker:</strong> Always performs Human Linter level, rarely goes deeper. You’ll know them by their “nit:” prefixed comments about variable naming and formatting. Sometimes can be too opinionated with their suggestions, so don’t be afraid to speak out.</p><p><strong>The Detective:</strong> Excels at Bug Catching. They’re the ones who spot edge cases you missed and ask, “what happens if this API call fails?” Maybe questions every edge case to an unfathomable degree so you need to tell them to relax, but most of the time they bring up good points.</p><p><strong>The Architect:</strong> Reserved for complex PRs, they question design decisions and suggest alternative approaches. They’re thinking about maintainability six months from now for a function that could just be a throwaway.</p><p><strong>The Rubber Stamper:</strong> Gives Level 0 approvals. Either they completely trust you, or they’re overwhelmed and not actually reviewing. Both scenarios are problematic in different ways and it would be ideal to try to get a review from another person, or inform them.</p><h3>Etiquette and Expectations</h3><p>Finally, let’s talk expectations and etiquette. There are unwritten social contracts that govern the entire review process. These rules are unwritten but violating them can make you come off as a bad engineer or an asshole to your colleagues. Funny how important things like these are never taught at school, but thankfully you have a nice guy like me to help you out with this ;).</p><h4>Before Submitting Your PR</h4><p><strong>Make sure your code actually works.</strong> The fundamental assumption is that you ran the code yourself and have verified that there are no obvious errors. Submitting broken code wastes everyone’s time and erodes trust. It is super convenient for the reviewer to see some media of the software working (images/videos) included in the PR description.</p><p><strong>Don’t hide test deletions or failures.</strong> If you removed tests or are aware of failing ones, be transparent about it in your PR description. Include your reasoning. Sometimes it’s justified, but reviewers need context.</p><p><strong>Use draft status appropriately.</strong> Set your PR as a draft if you’re still making major changes. Don’t assign reviewers to drafts unless you specifically want early feedback. People get pinged unnecessarily and may start reviewing incomplete work.</p><p><strong>Wait for a clean state before requesting review.</strong> Only assign people to your PR — or any form of requesting a review — when it has no merge conflicts and you’ve finished all major changes. A passing CI/CD pipeline is ideal, though some teams are comfortable reviewing while builds are still running.</p><h4>During the Review Process</h4><p><strong>Signal when you’re actively reviewing.</strong> Leave a comment like “Currently reviewing” or use an emoji reaction that your team has agreed upon. This prevents multiple people from duplicating effort and lets the author know their PR has attention.</p><p><strong>Respect ongoing reviews.</strong> If someone else is actively reviewing (as indicated by their comment or reaction), don’t merge the PR while they’re still working through it. Give them time to finish their analysis.</p><h4>After Getting Approval</h4><p><strong>Limit post-approval changes.</strong> You can make small lint fixes or address obvious typos, but avoid any functional changes without asking for re-review. When in doubt, ping the approver.</p><p><strong>You are completely accountable.</strong> Once the code is merged into production, you are the first person accountable for any sort of breaking change related to it. Even if the breaking change is not your fault (an external service for instance), you should take ownership to fix it, either with a git revert or rollback. At some companies, the accountability may be shared with the approvers too.</p><h4>The Meta-Etiquette</h4><p>The most important unspoken rule is that these rules themselves are negotiable and team dependent. What matters most is that everyone on your team shares the same expectations. When in doubt, ask. Most people appreciate directness over assumptions, and clarifying expectations upfront prevents friction later.</p><h3>Conclusion: Making the Implicit Explicit</h3><p>Do you know your own code review process? And what are the expectations for approvals at your team? I hope I was able to bring some insights to your engineering knowledge.</p><p>The healthiest teams eventually document their review expectations.</p><ul><li>“All database migrations require Architecture-level review”</li><li>“UI changes need at least one designer approval”</li><li>“API changes must be reviewed by someone from the consuming team”</li><li>“Hotfixes can skip style checks but need extra testing scrutiny”</li></ul><p>I hope that you enjoyed reading this article. If you find that your team does not have review expectations, take the initiative and write a doc for it!</p><p>Allan</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6cbf395f8f4b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Laravel — Randomized Form Testing Trick]]></title>
            <link>https://medium.com/@allankong/laravel-randomized-form-testing-trick-eb88247ba1ce?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/eb88247ba1ce</guid>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[laravel]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Sat, 31 May 2025 20:12:22 GMT</pubDate>
            <atom:updated>2025-05-31T20:12:22.943Z</atom:updated>
            <content:encoded><![CDATA[<h3>Laravel — Randomized Form Testing Trick</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/662/1*1jtpQSoGYSIBq95-3jcU6w.png" /><figcaption>Randomized Forms in Laravel</figcaption></figure><h3>Introduction</h3><p>While working with Laravel, I noticed that I was using an increasingly large amount of repeated form data for testing. For example, in the site that I am building now, ComputerScienceResources.com (coming soon), it’s important that I have many feature/integration tests centered around posting resources. I noticed that I was repeating form information, like this:</p><pre>$formData = [<br>  &#39;name&#39; =&gt; &#39;JavaScript for Beginners&#39;,<br>  &#39;description&#39; =&gt; &#39;An introductory course covering the basics of JavaScript programming.&#39;,<br>  &#39;image_url&#39; =&gt; &#39;https://example.com/images/js-course.png&#39;,<br>  &#39;page_url&#39; =&gt; &#39;https://example.com/courses/javascript-for-beginners&#39;,<br>  &#39;platforms&#39; =&gt; [&#39;Web&#39;, &#39;Mobile&#39;],<br>  &#39;difficulty&#39; =&gt; &#39;Beginner&#39;,<br>  &#39;pricing&#39; =&gt; &#39;Free&#39;,<br>  &#39;topic_tags&#39; =&gt; [&#39;Web Development&#39;, &#39;Frontend&#39;],<br>  &#39;programming_language_tags&#39; =&gt; [&#39;JavaScript&#39;],<br>  &#39;general_tags&#39; =&gt; [&#39;Interactive&#39;, &#39;Project-based&#39;, &#39;Self-paced&#39;],<br>]</pre><p>Then, I would use that form data in a function for testing, as follows:</p><pre>$response = $this-&gt;postJson(route(&#39;resources.store&#39;), $formData);<br>$response-&gt;assertRedirect(); // a redirect after successful creation</pre><p>I am a strong believer in two coding philosophies: repeating code is a waste of time, and tests should not be static, but property based. Let me break down what I mean in detail.</p><p>Repeated form data could easily be resolved by having a form saved as a variable and reusing it. However, this leads to my next point: I also believe in property-based testing. This means that instead of having expected inputs and expected outputs, we create randomized inputs with expected properties as outputs. Here is an extremely simplified example: Instead of 2 + 2 = 4, we can add any random two numbers and expect the output to be their sum (that is the property).</p><p>When you deal with randomized inputs, the domain space of your tests is wider and much more assured. For example, let’s say we had tests that made a POST request with 3 different inputs. I would feel quite confident that it works. But, if we had randomized inputs that ran 30 times each test run, I would feel certain that the code works (given that we defined the output properties correctly).</p><p>So, how did I go about easily generating massive amounts of randomized form data?</p><h3>Solution</h3><p>I have a small trick that combines the API Resources with the factory method (https://laravel.com/docs/12.x/eloquent-factories). When I design factories for my classes, I want the inputs to be wide-ranging. For example, with my ComputerScienceResources site. I have a resource factory defined as follows:</p><pre>public function definition(): array<br>{<br>  $platforms = config(&#39;computerScienceResource.platforms&#39;);<br>  $difficulties = config(&#39;computerScienceResource.difficulties&#39;);<br>  $pricings = config(&#39;computerScienceResource.pricings&#39;);<br>  return [<br>    &#39;name&#39; =&gt; fake()-&gt;name(),<br>    &#39;description&#39; =&gt; fake()-&gt;realText(),<br>    &#39;user_id&#39; =&gt; User::inRandomOrder()-&gt;first() ?? User::factory()-&gt;create(),<br>    &#39;page_url&#39; =&gt; fake()-&gt;url(),<br>    &#39;platforms&#39; =&gt; fake()-&gt;randomElements($platforms, rand(1, 5)),<br>    &#39;difficulty&#39; =&gt; fake()-&gt;randomElement($difficulties),<br>    &#39;pricing&#39; =&gt; fake()-&gt;randomElement($pricings),<br>  ];<br>}</pre><p>This is great for creating wide amounts of diverse data. But how do I convert it to form data? This is where API Resources come in handy (<a href="https://laravel.com/docs/12.x/eloquent-resources">https://laravel.com/docs/12.x/eloquent-resources</a>).</p><p>I can create form data from an existing model easily like so:</p><pre>class ComputerScienceResourceTestResource extends JsonResource<br>{<br>  public function toArray(Request $request): array<br>  {<br>    return [<br>      &#39;name&#39; =&gt; $this-&gt;name,<br>      &#39;description&#39; =&gt; $this-&gt;description,<br>      &#39;image_url&#39; =&gt; $this-&gt;image_url,<br>      &#39;page_url&#39; =&gt; $this-&gt;page_url,<br>      &#39;platforms&#39; =&gt; $this-&gt;platforms,<br>      &#39;difficulty&#39; =&gt; $this-&gt;difficulty,<br>      &#39;pricing&#39; =&gt; $this-&gt;pricing,<br>      &#39;topic_tags&#39; =&gt; $this-&gt;topic_tags,<br>      &#39;programming_language_tags&#39; =&gt; $this-&gt;programming_language_tags,<br>      &#39;general_tags&#39; =&gt; $this-&gt;general_tags,<br>    ];<br>  }<br>}</pre><p>However, now we have a new problem. How can we handle the fact that we need to have an existing model for the Resource API to work? Well, we can create a static helper function in the ComputerScienceResourceTestResource class. The job of this helper is to create a model using a factory, then convert it to form data. The result looks like this:</p><pre>public static function fake(array $overrides = []): array<br>{<br>  // Create the model with disabled events<br>  $model = Event::fakeFor(function () {<br>    return ComputerScienceResource::factory()-&gt;create();<br>  }, [TagFrequencyChanged::class]);<br>  // Transform it to API form<br>  $formData = (new self($model))-&gt;toArray(request());<br>  // Delete after getting the array to avoid polluting the DB<br>  $model-&gt;delete();<br>  // Merge and return<br>  return array_merge($formData, $overrides);<br>}</pre><p>There are some other things you have to consider as well in the helper, such as disabling events, making sure to remove the created model from the database, and having the ability to override some of the randomized fields.</p><blockquote>Furthermore, if you are using a package like <a href="https://spatie.be/docs/laravel-data/v4/introduction">https://spatie.be/docs/laravel-data/v4/introduction</a>. You have even better tools to convert the model to a form, but you will still require the helper function to ensure that you create a model, convert it to a form, and delete it after.</blockquote><p>So, I can use the helper function as follows:</p><pre>$formData = ComputerScienceResourceTestResource::fake();<br>$response = $this-&gt;postJson(route(&#39;resources.store&#39;), $formData);<br>$response-&gt;assertRedirect(); // a redirect after successful creation</pre><p>This can be run as many times as I like, and it is essentially like having multiple tests in one combined.</p><h3>Alternative: Worksome Request Factories</h3><p>Something I just discovered recently is that you can remove the need for the helper function by using a dedicated library: <a href="https://github.com/worksome/request-factories">https://github.com/worksome/request-factories</a>. In this library, you don’t use a model to generate your forms, but instead you rewrite form-specific Faker data. This makes sense, as it reflects a separation of concerns between the model factories and form factories. Soon, I will be migrating my existing test code to this library.</p><h3>Conclusion</h3><p>I hope I was able to share information about property-based testing, as well a trick I use to achieve that effect in Laravel!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eb88247ba1ce" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JavaScript is Misunderstood: A Decent Language Treated Worse Than It Deserves]]></title>
            <link>https://medium.com/@allankong/javascript-is-misunderstood-a-decent-language-treated-worse-than-it-deserves-0b6c97a1a0c6?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/0b6c97a1a0c6</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Mon, 05 May 2025 01:52:25 GMT</pubDate>
            <atom:updated>2025-07-18T03:36:28.241Z</atom:updated>
            <content:encoded><![CDATA[<h3>Introduction</h3><p>I recently watched a video by Computerphile about developers’ least favorite languages: <a href="https://www.youtube.com/watch?v=03lRzf7iSiU&amp;t=1s&amp;ab_channel=Computerphile">What’s Your Least Favourite Programming Language? (2024 soundcheck question) — Computerphile</a></p><p>At the top of the list was JavaScript.</p><p>All the bad features of JavaScript described in the video are as follows:</p><ul><li>Variable Hoisting</li><li>Lack of Structure</li><li>Untyped Nature</li><li>Poor Error Handling</li><li>A Mess of libraries</li></ul><p>I felt like there should be some leniency; there is quite a nice language underneath JavaScript’s flaws. The language has garnered a large amount of hate, and I feel that it doesn’t deserve the terrible reputation it has. We have been shoehorning JavaScript into places, there are a few bad apples in its wacky ecosystem, and it was never meant to reach the scale it has today.</p><p>Perhaps the language is hated more than it deserves, and I can convince you that it’s not actually a bad language.</p><p>So, hold on a second… why am I defending JavaScript?</p><p>Am I a mega fan of JavaScript? Not really.</p><p>The best way to describe my relationship with it is that I am forced to use it, as all software engineers are if they want to do web development.</p><p>I know people who are huge fans of JavaScript, glazing it any chance they get. There is also a huge trend of early-career developers who want to use JavaScript at every opportunity: tRPC, Node, Deno and the list goes on to infinity. There are also many people I know who despise JavaScript to the bone.</p><p>So, I took some time to really understand JavaScript through a deep dive, to consider both perspectives of hate and love. I read the book: “JavaScript: The Good Parts.” Furthermore, I went though a good chunk of Mozilla Developer Network’s docs. I can say that “JavaScript: The Good Parts” was quite a nice read. But honestly, the book should be called “JavaScript: The Good Parts and Bad Parts.” There were an equal number of good things as bad things about JavaScript in this book.</p><p>I realized that there is basically no other language in the world that is like JavaScript, which is influenced by so many languages: Scheme, Self, Java (syntax), Perl (regex). But, even after reading, I still can’t see myself thinking that the language is amazingly well designed. I wasn’t like the developers who love it madly.</p><p>But I also didn’t see myself on the other side, like people who hate every little bit of the language. My feelings are more of a balance; I quite liked the language and thought it to be quite decent.</p><h3>JavaScript is Misunderstood: It does not deserve all the hate it gets</h3><p>What I’m arguing is that while JavaScript is frequently criticized for its quirks and inconsistencies, much of this disdain arises from widespread misuse, poor understanding, and ecosystem challenges rather than inherent flaws in the language itself. JavaScript is powerful and dynamic language — though it contains faults — that has brought forth various innovations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/711/1*GrZGFCpY0LHKm7R_i7IvpA.png" /></figure><p><strong>Acknowledgement of Valid Arguments</strong></p><p>I do want to acknowledge that JavaScript is a language that was rushed. There were a lot of rough edges, especially at its release. It wasn’t until ES5 that most major browsers became supportive of JavaScript. So, I’d like to talk about some of the biggest issues with JavaScript first.</p><p>The first criticism to tackle is the lack of an integer type. In JavaScript, you can only use floats, adhering to IEEE 754. This is not really a big problem unless you work with numbers outside the range of 2⁵³ — 1 or need native precision.</p><p>There is the infamous bug:</p><pre>0.1 + 0.2 === 0.3 // true</pre><p>But this big has existed in almost every language, including Python, C, Java, C++, and others. That’s why there is a dedicated Decimal class in most languages. However, JavaScript lacks one, which can be troublesome. As a result, you need to install a library like mathjs to handle high precision.</p><p>This brings me to my next point, which is that JavaScript feels like it’s missing a proper standard library. Even an operation as basic as deep cloning an array is missing. Here are a bunch of major standard features that are missing: Enum support, Date formatting, assertions for testing, and range or iterable utilities.</p><p>One powerful aspect of JavaScript is coercion. Coercion is an amazing tool, but it can be a bit confusing, and its rules can be seen as inconsistent. WTFjs — which shows a ton of JS funny edge cases <a href="https://github.com/denysdovhan/wtfjs?tab=readme-ov-file#-is-truthy-but-not-true">https://github.com/denysdovhan/wtfjs</a> — has most of its WTF’s from coercion. Some of the oddest ones are:</p><pre>[] + {} // &quot;[object Object]&quot;<br>[] == ![] // true<br>null == undefined // true</pre><p>Another major problem of JavaScript is that `this` does not behave as one would intuitively expect (binding to the local object). Instead, it follows a different rule: In a function, `this` refers to the global object. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this</p><p>Here is a program that uses a helper function, and would not work:</p><pre>function myObject()<br>{<br>  this.value;<br>  this.adder;<br>}<br><br>let obj = new myObject();<br>obj.value = 2;<br>obj.adder = function ()<br>{<br>  function helper () {<br>    this.value += 2; // Problem, `this` refers to the global object, not the `obj` object<br>  };<br><br>  helper();<br>}<br><br>obj.adder();<br>console.log(obj.value); // still 2, and no errors thrown</pre><p>This can be mitigated by calling another object method instead (since it binds `this` to the object), or to create a variable called `that` and use `that`, example:</p><pre>obj.adder = function ()<br>{<br>  let that = this; // using a new variable (that) to reference `this`<br>  <br>  function helper () {<br>    that.value += 2;<br>  }<br>  helper();<br>}</pre><p>The above are all valid problems with the language, and there are still more which I have not even mentioned yet: silent failures, arrays being objects, variable scope, and semi-colons being optional. Despite these flaws, the language is not terrible. A better description for the language would perhaps be unpolished. In the end, JavaScript remains incredibly versatile and widely used, and with modern tooling (like Lodash and ESlint) and best practices, many of these issues can be mitigated.</p><p><strong>The High Number of Frameworks is not the language’s fault</strong></p><p>Now, we can start defending the language.</p><p>At first glance, it seems like there are many JavaScript frameworks which exist solely for the sake of creating frameworks. One could ask, ‘why did we make jQuery when vanilla is good enough, or why is there Angular, React, Vue, and so on?’ Then, one could make the brash conclusion that perhaps the reason is that JavaScript is a terrible language</p><p>But I’d like to argue that the reasoning behind this large number of frameworks lies in the flaws of the original DOM API.</p><p>Early on in the web’s history, when JavaScript first came out, the DOM was a mess (<a href="https://johnresig.com/blog/the-dom-is-a-mess/">https://johnresig.com/blog/the-dom-is-a-mess/</a>). This is a great talk that you should listen to that addressed the lack of standardization in the DOM API. This was the start of a very long chain of problems that followed.</p><p>There was a lack of standardization with web browsers’ DOM APIs, and normalizing functionality between browsers was hellish. So, thanks to JavaScript being the flexible language it is, John Resig created jQuery; it reduced boilerplate and normalized browser functionality. This was a huge help for the language. JavaScript was easier to write and people generally advocated for the use of jQuery over vanilla JS. I won’t mention the less popular frameworks (such as Prototype and Coffee Script) for the sake of time. I’m also ignoring Java Applets, Adobe Flash and Web Assembly.</p><p>People used jQuery; it made JavaScript so much easier and normalized. But web development demands grew: Google wanted to develop web applications that were single page applications, and with less boilerplate. So, they invented a new JavaScript framework with modern app requirements, with a focus on declarative code: dependency injection, dynamic rendering, and two-way binding.</p><p>Did this mean that jQuery or JavaScript became bad? No, there was simply a different approach needed for larger and more complex software applications. There was also a trend throughout the 2010’s to start using less semantic HTML and rely more on JavaScript for UX/UI. For example, instead of using the standard HTML form, people would prefer to implement a dynamic Form with JavaScript to override default behavior and perform side effects. So, it was natural that some jQuery codebases became spaghettified, and a new framework would replace jQuery. Refactoring and inventing abstractions upon complex code is a natural part of software development, in this case, with Angular.</p><p>Angular 1.0 was quite amazing. But, as we created more complex JavaScript applications, there were a lot of performance problems. Some common problems were two-way binding(they used a digest cycle), weird edge cases with $scope, and a very steep learning curve. I’ve never personally used Angular 1.0, so I wouldn’t know much about it. But the fear of it still resonates with many developers online.</p><p>Naturally, a new framework to improve speed and modularity took over. Facebook made React, which used a virtual DOM, and focused more on one-way data flow and component-based architecture. Then, Evan You decided to make a simpler and more lightweight version of that, and invented Vue.js. Then, Google rewrote Angular, and it became Angular v2.</p><p>There are also a lot more frameworks to mention, such as Flutter. The framework was created after Dart as a language didn’t take off; its purpose was to replace JavaScript entirely with an object-oriented and fast compiled language like Dart.</p><p>Outside of frameworks, there was also TypeScript by Microsoft which adds type safety to JavaScript and transpiles to it. This did take off because it did not try to replace JavaScript entirely, which so many systems — like web browsers — are stuck with. Instead, JavaScript became a subset of a stronger-typed and stricter language.</p><p>We are now in modern day and have reached a point where we have all these frontend frameworks that made sense to develop at the time. Furthermore, we have been advocating for people to learn these frameworks over using vanilla JavaScript. But even though some tools — like jQuery (or Alpine JS being the modern-day equivalent) — are better than others for certain tasks, it seems that popularity has taken over practicality in practice. It is almost like the go-to framework to use for anything is React. I also want to mention HTMX (I’m a huge fan), and I think not enough people consider it. Instead of considering all tools for the job, people like to jump on the React hype-train.</p><p>Even though there are already so many existing tools, the JavaScript community is keen on creating more frameworks and libraries. There are two categories of people who are creating new frameworks: those who see a different/better way to do front end development, and those who just want to make another framework. On the former, the web is a complicated and opinionated platform, people will come up with new ways to render the DOM in ‘better’ ways, and this will continue to happen forever. About the latter, these are just people who either want to make a framework for fun or perhaps have the aspirations of going viral. We must differentiate the language itself from the fact that the DOM API must use JavaScript, which results in many different JavaScript frameworks.</p><p>In conclusion, one cannot say that JavaScript is a bad language because it has too many frameworks. The major frameworks of JavaScript were created for a good reason at the time. If web browsers standardized the DOM API a long time ago, there would be far less JavaScript frameworks. Furthermore, one cannot attribute the community’s desire to spin up more frameworks a fault of the language. The faults of the community are not the faults of the language.</p><p><strong>The Library’s Ecosystem is the Community’s Doing</strong></p><p>The JavaScript ecosystem is bloated. This is well-known in the community as well, with jokes along the lines of npm modules being the heaviest mass in the universe. In 2023, there were 3 million npm packages (<a href="https://blog.sandworm.dev/state-of-npm-2023-the-overview#heading-total-packages-count-3342873">https://blog.sandworm.dev/state-of-npm-2023-the-overview#heading-total-packages-count-3342873</a>). That is quite the huge amount; for comparison, python’s PyPi has more than 530,000 Python packages available as of 6 May 2024. (<a href="https://en.wikipedia.org/wiki/Python_Package_Index">https://en.wikipedia.org/wiki/Python_Package_Index</a>)</p><p>The reason behind this large number of packages is a mix of many things.</p><p>JavaScript is everywhere: Node, React Native, Electron, web development, etc. It is natural that there are many packages to fill in niches.</p><p>I also mentioned earlier that JavaScript is missing a standard library, and people have taken matters in their own hands.</p><p>But the biggest reason is that the community is focused on a culture of small, composable packages. One of the UNIX philosophies is to “make each program do one thing well.” It seems that the community has taken this idea to the extreme. There are programs like is-even, left-pad, or slugify, which one could implement themselves in a time of 15 minutes maximum.</p><p>This npm explosion of micro-packages has created a bad reputation for JavaScript, with security &amp; maintenance risks, bloated dependencies, and fragmentation of the ecosystem. JavaScript was, however, merely the tool amid all of this. JavaScript, as a language, doesn’t dictate how developers structure projects, write code, or distribute packages. It doesn’t require developers to create thousands of micro-libraries. That’s a cultural choice, largely shaped by community practices, not language features. Combine that with the “small reusable module” philosophy from Node.js, and you have a recipe for explosive growth. The language didn’t enforce this; it merely enabled it.</p><p>I think that yes, JavaScript perhaps started the explosion with its rough edges, but the community really overkilled the ecosystem.</p><p><strong>Core Misunderstandings of the language</strong></p><p>I think there is another big reason that people hate JavaScript: people have not been bothering to understand the language at a fundamental level.</p><p>People see some of JavaScript’s different nature — prototypical inheritance, execution model, etc. — as traits of a poorly designed language. One could argue that JavaScript is poorly designed because of the valid arguments I’ve already touched upon. But, to argue that this language has no structure is wrong.</p><p>JavaScript is fundamentally a prototypal object-oriented language. It does have a solid foundation of structure; it just isn’t very clear about it. I think this is the biggest point of misconception on the language. There is a big discrepancy between what people think JavaScript is, and how it works.</p><p>One example I want to mention is ‘classes’, introduced in the ES6 revision. ES6 was an amazing update to JavaScript; one could argue it killed CoffeeScript as the language was now matured enough. But now, there are ways to declare ‘classes’ in JavaScript.</p><p>The old — and perhaps ‘correct’ — way to create objects was with Object Constructors, which is akin to JavaScript’s true nature, binding variables to the local object.</p><pre>function Car(name, year)<br>{<br>  this.name = name;<br>  this.year = year;<br><br>  this.print = function() <br>  {<br>    console.log(this.name + &quot; &quot; + this.year);<br>  };<br>}<br><br>car = new Car(&#39;DMC DeLorean&#39;, 1955);<br>car.print();</pre><p>However, we can also declare the same thing in the ES6 class format:</p><pre>class Car {<br>  constructor(name, year) {<br>    this.name = name;<br>    this.year = year;<br>  }<br><br>  print()<br>  {<br>    console.log(this.name + &quot; &quot; + this.year);<br>  }<br>}<br><br>car = new Car(&#39;DMC DeLorean&#39;, 1955);<br>car.print();</pre><p>This makes JavaScript look like a language that supports classical inheritance, such as Java, C#, Python, and C++. But the problem is that this disguises the true nature of JavaScript, which uses a prototypical-inheritance system (<a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object_prototypes">https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object_prototypes</a>).</p><p>If you looked at the class example above, and think that JavaScript is like Java, this code below would make no sense:</p><pre>car = new Car(&#39;DMC DeLorean&#39;, 1955);<br><br>details = {<br>  creator: &#39;Emmett Brown&#39;<br>};<br><br>Car.prototype.details = details;<br>console.log(car.details.creator);</pre><p>Prototypical inheritance does not follow classical inheritance of classes, but rather the inheritance of objects. Furthermore, JavaScript has the added feature of flexibility: adding and removing prototypes at runtime.</p><p>So, I would say that a lot of people don’t bother learning JavaScript for what it is and how it works. The problem with my claim, however, is that I don’t have any empirical data to show for this. I guess the closest would be the fact that we say <strong>Vanilla JavaScript</strong> to state native JavaScript. The original term was satirically used as the name for another JavaScript framework: <a href="http://vanilla-js.com">http://vanilla-js.com</a></p><p>Another example of people not really bothering to learn about JavaScript would be how many people also don’t understand the event queue, and how JavaScript in a single-threaded worker can handle multiprocessing (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Execution_model</a>). Again, I don’t have any evidence to back me up on this, I just see a lot of confusion about the event queue on Stack Overflow.</p><p>Furthermore, since it is advocated to use a framework over vanilla JS, most people have only worked with JavaScript in a framework setting. It is easy for one to completely disregard learning the fundamentals of JavaScript as a standalone language. It is the kind of language that allows you to get away with messy code thanks to its dynamic and expressive nature. Inadvertently, this leads to a superficial understanding of the language’s core principles.</p><p>With so many people working with JavaScript in a framework setting, there can be a lot of badly written and diverse JavaScript code. There happens to be no definitive way to write JavaScript code. Unlike Golang, where codebases will look very similar, JavaScript can range from reasonable to JDSL (<a href="https://thedailywtf.com/articles/the-inner-json-effect">https://thedailywtf.com/articles/the-inner-json-effect</a>). I think that if we look at JavaScript, from a very high-level overview — ignoring the current ecosystem — the language has quite a lot a beauty to it that we must appreciate. I think that more people should learn about this language standalone and appreciate the beauty in it.</p><p><strong>The Beauty of the Language</strong></p><p>I want to take a short amount of time to just talk about how nice JavaScript is, despite its rough edges.</p><p>JavaScript can be surprisingly elegant. It borrows a lot of ideas from functional programming; hence functions are treated as first-class citizens. Hence, we have access to higher order functions like mapping, filtering, forEach. In addition to that, it is very easy to create anonymous functions, with some of the shortest and cleanest syntax seen in any language:</p><pre>const add = (a,b) =&gt; a + b<br>add(1,2) // 3</pre><p>This elegance is enhanced by the notation to create an object. Objects can be easily represented, with its variables and functions like so:</p><pre>const ringo = {<br>  name: &quot;Ringo Starr&quot;,<br>  instrument: &quot;drums&quot;,<br>  year: 1940,<br>  print: function() {<br>    console.log(this.name + &quot; played the &quot; + this.instrument + &quot; and was born in &quot; + this.year);<br>  }<br>};<br><br>ringo.print();</pre><p>In fact, the JavaScript Object Notion is so simple and easy to view that we have adopted it as the go-to standard for formatting data: JSON.</p><p>Furthermore, people complain a lot about JavaScript’s global variables. But, since ES6, scope is no longer limited to function or global scope using let or const. This created a powerful feature: closures. It allows you to combine a function with the information of the environment where the function was declared. (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures</a>). A nice example would be:</p><pre>function makeAdder(x) {<br>  return function (y) {<br>    return x + y;<br>  };<br>}<br><br>const add5 = makeAdder(5);<br>const add10 = makeAdder(10);<br><br>console.log(add5(2)); // 7<br>console.log(add10(2)); // 12</pre><p>The makeAdder function now has information about the lexical environment — context in which variables are defined — and can return a function with that. This is powerful since JavaScript can “remember” variables from its surrounding scope even after the outer function has finished running. This can remove the need for duplicating code or using global variables. Furthermore, since JavaScript does not have private variables, one can come up with a workaround using closures, such as in the following:</p><pre>function createBankAccount(initialBalance) <br>{<br>  let balance = initialBalance; // cannot be accessed <br><br>  return {<br>    deposit(amount) <br>    {<br>      balance += amount;<br>    },<br>    getBalance() <br>    {<br>      return balance;<br>    }<br>  };<br>}<br><br>const account = createBankAccount(100);<br>account.deposit(50);<br><br>console.log(account.getBalance()); // 150</pre><p>Now, the balance cannot be accessed directly.</p><p>I think that is enough on the beauty of the language, you can research more into the language with these recommendations:</p><p><a href="https://github.com/getify/You-Dont-Know-JS">https://github.com/getify/You-Dont-Know-JS</a></p><p><a href="https://www.oreilly.com/library/view/javascript-the-good/9780596517748/">https://www.oreilly.com/library/view/javascript-the-good/9780596517748/</a></p><p><strong>Conclusion</strong></p><p>I hope I’ve been able to shed some light on how JavaScript can be quite a nice language at times. I think that much of the hate towards it has come from misuse and the bad reputation of its ecosystem, rather than the language itself being terrible.</p><p>JavaScript is a decent language treated worse than it deserves.</p><p>Thank you for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0b6c97a1a0c6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Software Terminology Misconceptions That Annoy Me More Than They Should]]></title>
            <link>https://medium.com/@allankong/software-terminology-misconceptions-that-annoy-me-more-than-they-should-cc859b44d6fa?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/cc859b44d6fa</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[computer-science]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Tue, 01 Apr 2025 16:41:46 GMT</pubDate>
            <atom:updated>2025-04-01T16:41:46.650Z</atom:updated>
            <content:encoded><![CDATA[<p>So, today is April Fools. I wanted to write an article that was a little more on the ‘joke’ side, while still retaining good information, and being factual.</p><p>Over the past few years, I’ve been building a mental list of small misconceptions other people in software development say that bothers me more than it really should. Typically, these examples are two things that are not the same but are used interchangeable by the masses.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/794/1*IIp_8PFWQee5x2ZwCv5gWg.png" /></figure><p>So, whether it is to share information for the sake of teaching or catharsis, I will introduce the list below:</p><h3>A Modem and a Router are two different things</h3><p>Stop saying that your router is what connects you to the internet!</p><p>People interchange this one the most. Let me get this straight:</p><ul><li>The modem is what connects your network (typically your home) into the internet. Without the modem, you won’t have any internet access.</li><li>The router is what <em>routes</em> the IP packets between networks. It could be to another network, your subnetworks, the internet, whatever. Basically, it handles the <strong>routing </strong>of your network.</li></ul><p>The modem’s job is very simplistic, all it does is transmit your network data in a transmission medium that is suitable for you to reach the internet. This is not as complex as the role which the router must take on. Henceforth, people typically only have a single device in their home: a modem and router combined into one device. Since we need a name for this device, I guess it is fine to call it a router. But don’t you dare say that a router’s job is to connect you to the internet.</p><p>I hope we understand the differences. In fact, let’s get more technical.</p><p>The router uses several notable protocols for handling the routing of IP packets. These include Network Address Translation (NAT). Border Gateway Protocol (BGP) which can be split into internal (iBGP) or external (eBGP).</p><p>NAT is to convert the local IP addresses in your network to the public IP your ISP gave you. BGP is to help determine the routing of your IP packets either inside your network, or to a larger external network, like the internet.</p><p>Meanwhile, a modem uses protocols which I have never heard of in my life. One of them is Gigabit Passive Optical Network (GPON). This is used in fiber-optic networks.</p><p>Now, onwards to more rants!</p><h3>People say Big O Notation in Interviews when they mean Big Theta</h3><p>During technical interviews, it’s become a standard to be asked the Big O notation of your algorithm. Typically, what the interviewer is asking for is the time complexity of your algorithm since they want to gauge if you know how fast the code you wrote is. The problem is that Big O is probably not what they are asking for.</p><p>The mathematical definition of Big O is as follows:</p><blockquote>Let f(n) and g(n) be functions that map positive integers to positive real numbers. We say that f(n) is O(g(n)) (or f(n) ∈ O(g(n))) if there exists a real constant c &gt; 0 and there exists an integer constant n₀ ≥ 1 such that f(n) ≤ c ∗ g(n) for every integer n ≥ n₀.</blockquote><p>This seems like a mouthful but, I can explain slowly. Let’s say <em>f(n)</em> and g(n) are two algorithms that you wrote. Now, let’s say that past a certain input size n₀, maybe it is n = 1000, the algorithm <em>g(n)</em> is now much slower than <em>f(n)</em>. In fact, <em>g(n)</em> is always slower than<em> f(n)</em> by at least a constant, called c.</p><p>So, we can say that the algorithm<em> f</em> is Big O of <em>g</em>. So, in colloquial terms, Big O is to define the upper bounds of the algorithm.</p><p>Understood? Well, technically, by the mathematical definition, we could just answer the interview question above:</p><blockquote>What is the Big O Notation of your algorithm?</blockquote><p>With the same response every time: Big O(n!).</p><p>Since that is probably the slowest algorithm one could make. Obviously, you shouldn’t do this since you will fail the job interview and be ridiculed for considering that your algorithm was that slow.</p><p>But the correct term that the interviewer <em>should</em> be using is Big Theta (Θ).</p><p>Big Theta (Θ) is for comparing two functions (algorithms), f and g. If f∈Θ(g), then it has the same asymptotic complexity as g.</p><p>Another cool way to think of this is that if you divide f by g, and do the limit of the input n to infinity, then you will get some constant k.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/188/0*02U_4EIH7EDJajYN" /></figure><p>So, if f ∈ Θ(Log(n)), then you know how fast your algorithm is, not the upper bound, not the lower bound, but the actual speed. But, whatever, we will keep saying Big O in the industry as if it were the same thing.</p><h3>DevOps is a Cultural Practice, not a Job</h3><p>Please stop saying that you are a <em>DevOps </em>Engineer.</p><p>DevOps was a cultural movement that started around 2007 when people realized that deployments of infrastructure and collaborations between the development team was lacking. So, there came a new ideology that was to introduce the use of automated tooling, closer collaboration, encouraging work environments that utilized the growth mindset, and better testing. This allowed the collaboration between teams to be stronger, autonomous, and transparent.</p><p>One of the poster child’s (or is it poster children?) of DevOps is Etsy. You should read more about it. I found a nice article <a href="https://www.simform.com/blog/etsy-devops-case-study/">https://www.simform.com/blog/etsy-devops-case-study/</a> that explains it.</p><p>So, what is the terminology misconception that bothers me? Well, people use the term <em>DevOps </em>Engineer as if it were a role to cover everything related to infrastructure. The right term would be infrastructure engineer or system administrator.</p><p>I think the best comparison for calling someone a DevOps Engineer is calling myself a Chinese New Year Engineer because I am good at making dumplings and fried rice.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/601/1*IbuL8Y1345t3cpFiF5pAGg.png" /></figure><p>If you are not convinced yet, take a look at this discussion here: <a href="https://www.reddit.com/r/devops/comments/1f0u1nn/why_are_there_people_in_this_sub_who_thinks/">https://www.reddit.com/r/devops/comments/1f0u1nn/why_are_there_people_in_this_sub_who_thinks/</a></p><h3>Scrum and Agile are Different!</h3><p>To summarize quickly, scrum is a subset of agile.</p><p>Agile is a broad philosophy for software development. It involves iterative development, collaboration, and adaptability. The main focuses on agile is the ability to react to change quickly. This involves getting early interaction with the customers and collaborating. The 12 principles behind Agile Manifesto can still be viewed in glorious detail: <a href="https://agilemanifesto.org/principles.html">https://agilemanifesto.org/principles.html</a>.</p><p>These ideas are a complete contract from the traditional waterfall planning model, that involved a singular long planning session, and afterwards only followed development. Agile is a beautiful idea, and those 12 principles lead the way to two specific frameworks that adopted agile:</p><p><strong>1. Extreme Programming (XP)</strong></p><p>I will highlight some of the important features: customer obsession, extreme teamwork, and constant feedback. On the development side, there are small releases, pair programming, and test-driven development. More details can be viewed at: <a href="http://www.extremeprogramming.org">http://www.extremeprogramming.org</a>. It is quite a nice read.</p><p><strong>2. Scrum</strong></p><p>Now this is what we wanted to talk about. Scrum is another framework of agile, the name actually come from Rugby, where a team comes together to move the ball forward. The framework has three main pillars of focus: transparency, inspection and adaptation. But I don’t want to get into the details. If you are curious, it is here: <a href="http://www.scrum.org/resources/what-scrum-module">www.scrum.org/resources/what-scrum-module</a></p><p>I think the ideologies behind scrum are quite nice. It is quite efficient for fast software development and growth amongst team members. Debating whether scrum is a good framework in practice is a completely different topic.</p><p>However, I want people to know, if they say they hate <strong>agile</strong>, they better know that they are referring to the broad philosophy, not scrum or XP!</p><h3>Stop Calling AI and LLMs The Same</h3><p>Artificial intelligence is defined from Wikipedia as:</p><blockquote>capability of computational systems to perform tasks typically associated with human intelligence.</blockquote><p>Just remember that LLMs are a subset of AI’s. I am a little tired of hearing the word AI tossed around so often for LLMs. There are so many other cool AI software’s out there:</p><p>- AlphaGo and AlphaZero (from DeepMind), an amazing unsupervised deep neural network.</p><p>- OpenAI Five, an AI to win Dota 2. Yes, OpenAI once did not LLM related things.</p><p>- NASA’s ST5 Antenna Design being derived from a genetic algorithm. <a href="https://www.jpl.nasa.gov/nmp/st5/TECHNOLOGY/antenna.html">https://www.jpl.nasa.gov/nmp/st5/TECHNOLOGY/antenna.html</a></p><p>- SAT Solvers, determining how to make a Boolean formula true.</p><p>There are so many cool AI techniques that predate LLMs. If you are interested in learning about Artificial Intelligence, take a look at this amazing course: <a href="https://www.edx.org/learn/artificial-intelligence/harvard-university-cs50-s-introduction-to-artificial-intelligence-with-python">https://www.edx.org/learn/artificial-intelligence/harvard-university-cs50-s-introduction-to-artificial-intelligence-with-python</a></p><h3>Not Every HTTP API is a REST API</h3><p>I think that the idea of what REST is, is quite misunderstood. Most people know that it stands for Representational State Transfer. Creating an HTTP API is not creating a REST API, get that out of your head. Stop trying to fill in buzz words with your tech stack and say that you have a REST API.</p><p>Furthermore, don’t bother with small details like which HTTP verb is more RESTful: PATCH vs UPDATE. Apparently, HTTP verbs were not mentioned in the original dissertation (<a href="https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm</a>). REST was just a proposed architectural style that was to guide the early internet into conforming standards.</p><p>I think this blog post is the best summary to the problem: <a href="https://twobithistory.org/2020/06/28/rest.html">https://twobithistory.org/2020/06/28/rest.html</a></p><p>Furthermore, there are some criteria in the original REST specifications which some people would never do: uniform interface, and one part of that is being HATEOAS compliance. Again, most people don’t know what HATEOAS. To summarize quickly, a client could have no idea how to navigate a website beyond simple hypermedia — links for example — and navigate the site by the server response. A great article on this is by HTMX (an amazing framework): <a href="https://htmx.org/essays/hateoas/">https://htmx.org/essays/hateoas/</a></p><p>So, we can assume that most API endpoints are not complacent with being a uniform interface. I would say that either your API is RESTlike, or it follows a specific specification like (OpenAPI): <a href="https://swagger.io/specification/">https://swagger.io/specification/</a></p><p>But, in the end, I think that the word RESTful is becoming just a buzz word that will keep being tossed around into complete meaningless until it becomes synonymous with HTTP API.</p><h3>Monoliths are not Bad</h3><p>Developers hear monolith and think evil, slow, unscalable. I think that is wrong for so many reasons.</p><p>First, I find that monoliths are perfect for 90% of jobs out there. Most software out there usually hits a maximum of 4000 monthly users. What is the source? I eyeballed it, let me know if I am wrong. Second, monoliths are simple to maintain, your codebase is in one single location, and one can hopefully easily view what part of the monolith is responsible for what part. I think that speed of development is the most important thing when it comes to software (besides software quality).</p><p>Now, one could say, “microservices are much more organized since they have a single responsibility.” That could be possible, but even if you somehow managed to organize the separation of concerns between the services perfectly, there comes the problem of handling scalability, communication, and being independent from other services. If most of your services are broken after a single service is down, it’s not a good microservice system; perhaps it shouldn’t even be called that.</p><p>One article that supports the point I am making about monoliths is from DHH (the creator of Ruby on Rails) <a href="https://signalvnoise.com/svn3/the-majestic-monolith/">https://signalvnoise.com/svn3/the-majestic-monolith/</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/1*VPBeR5_SIKIiRdgvlTUFPA.png" /></figure><p>So, basically, don’t overengineer your software. Bother with overengineering once you need to. Everyone wants to role play as a solutions architect at Google but focus on what is needed from your users first.</p><h3>OAuth is for Authorization, not Authentication</h3><p>Authorization is knowing what someone is allowed to access.</p><p>Authentication is knowing if someone really is who they are claiming they are.</p><p>OAuth was designed as an authorization framework that allowed granting a client application limited access to a user’s resources without exposing the user’s credentials. Furthermore, Authorization requires Authentication, you cannot have any sort of authorization of an individual unless you can authenticate such individual.</p><p>What you really mean when you say you are using OAuth for Authentication is probably that you are using OpenID Connect, or you are just accessing an API with an access token and want to sound fancy. To use OAuth, the application needs to be wrapped around some existing authentication layer, whether it is your own cookie implementation, or OpenID.</p><p>If you are still confused, this is an amazing article to understand more: <a href="https://oauth.net/articles/authentication/">https://oauth.net/articles/authentication/</a></p><h3>Do not Repeat Yourself is not about Removing Duplicate Code</h3><p>DRY is not about duplicate code being evil. It’s the duplication of knowledge, or redundant knowledge being evil.</p><p>Don’t be the kind of developer that sees a line of code repeated during code reviews and write “nitpick”, this code is repeated.</p><p>Here is a very extreme example to prove my point:</p><pre>name: string().required(&quot;Name is required&quot;).max(100, &quot;Max 100 chars&quot;),<br>page_url: string().url(&quot;Must be a valid URL&quot;).required(&quot;URL is required&quot;),<br>image_url: string().url(&quot;Must be a valid image URL&quot;),<br>platforms: array()<br>.of(string())<br>.min(1, &quot;At least one platform is required&quot;),<br>description: string().required(&quot;Description is required&quot;).max(4000),<br>difficulty: string().required(&quot;Difficulty level is required&quot;),<br>pricing: string().required(&quot;Pricing information is required&quot;)</pre><p>Notice how there is a lot of repeated code here. The idea is that the knowledge is unique each time.</p><p>But another thing to mention is that it’s also okay to duplicate knowledge sometimes. It’s called being a little bit WET (<em>we enjoy typing)</em>. It’s okay to duplicate knowledge for a bit as long as things remain readable, and maintainable. Finding the source of shared knowledge can be quite tedious since it is no longer localized.</p><p>So, basically, it’s okay to do moist coding. Don’t follow a single silver bullet. There is always a balance to software.</p><h3>Conclusion</h3><p>Well, I hope today was a very informative and educational April Fools day, where you will no longer annoy a percentage of software developers with these small misconceptions that don’t even matter. But you can also continue to annoy people too. If you are interested in that sort of thing, don’t let me stop you.</p><p>Thanks for listening to another of my rants!</p><p>— Allan</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cc859b44d6fa" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Magpie CTF 2025 Writeup]]></title>
            <link>https://medium.com/@allankong/magpie-ctf-2025-writeup-9f2e4d640532?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/9f2e4d640532</guid>
            <category><![CDATA[ctf]]></category>
            <category><![CDATA[cybersecurity]]></category>
            <category><![CDATA[ctf-writeup]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Mon, 24 Mar 2025 22:07:14 GMT</pubDate>
            <atom:updated>2025-03-24T22:07:14.309Z</atom:updated>
            <content:encoded><![CDATA[<p>I recently did the Magpie CTF 2025, a Capture the Flag contest that is hosted by the Cyber Security Club at the University of Calgary (<a href="https://cybersec-ucalgary.club">https://cybersec-ucalgary.club</a>).</p><p>The contest was very well organized and filled with challenging problems. The GitHub repository can be found here: <a href="https://github.com/infosec-ucalgary/magpieCTF-2025">https://github.com/infosec-ucalgary/magpieCTF-2025</a></p><p>My team did quite well, landing in the top 10, which was quite a nice feeling.</p><p>But, in addition to the CTF challenge, there was a writeup challenge. You could submit writeups (solutions/guides to challenges), and the top three were selected. This was my first time doing a writeup and I wished that there were more examples on the internet.</p><p>So, I managed to snag first place in the writeups, and I wanted to share it below!</p><h3>Magpie CTF 2025 cops-like-ciphers-and-cookies</h3><h3>Written By</h3><p><strong>Team</strong>: education is fun</p><p><strong>Member</strong>: SadBread</p><h3>Category</h3><p>Web</p><h4>Description</h4><p>New email from cors@nypd.gov:</p><p>We believe that there is a vulnerability within the NYPD landing page, that has been overlooked for way to long. Not only that but it was exploited within the days following Krypto’s murder.</p><p>Check to see what the vulnerability is, and if it has anything to do with our suspects.</p><p>Edward Cors — NYPD</p><p><a href="http://challenges.magpiectf.ca:13000/">http://challenges.magpiectf.ca:13000/</a></p><h4>Introduction</h4><p>Only a website is provided: <a href="http://challenges.magpiectf.ca:13000/">http://challenges.magpiectf.ca:13000/</a></p><p>Upon visiting the website link, we are greeted with a webpage that looks like the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UbQXeWhqF6cO6rPr1rNq3A.png" /></figure><p>There does not seem to be much information related to vulnerabilities on the web page provided, only a to-do list on the left and a mission briefing summary on the right.</p><p><strong>However,</strong> one thing that is notable on the website is that there is a URL to a webpage: <a href="https://themindfool.com/consistency-is-key.">https://themindfool.com/consistency-is-key.</a></p><p>Upon clicking on the article, one can observe that it is simply a mental health blog. There is nothing to do with the CTF in the content of the blog.</p><p>Given that <strong>MagpieCTF does not own the domain `themindfool.com`</strong>, the article title — rather than the content — is likely a hint: consistency is key. Since we don’t know anything about this website, we will just keep this in the back of our mind.</p><h4>Reconnaissance</h4><p>Naturally, one of the first things to do when analyzing a webpage is inspecting the source of the page. The shortcut for this is typically <strong>(Control+U)</strong> on web browsers.</p><p>Or, one can curl the webpage, whilst also viewing the response headers (with `-i`) in case there is anything important in them</p><pre>$ curl -i http://challenges.magpiectf.ca:13000</pre><p>The results for the curl are as follows:</p><pre>HTTP/1.1 200 OK<br>X-Powered-By: Express<br>Set-Cookie: eiejmfm-yfgp=iirkb; Path=/; HttpOnly; SameSite=Lax<br>Accept-Ranges: bytes<br>Cache-Control: public, max-age=0<br>Last-Modified: Sun, 23 Feb 2025 01:14:51 GMT<br>ETag: W/&quot;b04–195305f0f63&quot;<br>Content-Type: text/html; charset=UTF-8<br>Content-Length: 2820<br>Date: Fri, 28 Feb 2025 01:01:03 GMT<br>Connection: keep-alive<br>Keep-Alive: timeout=5<br>&lt;!DOCTYPE html&gt;<br>&lt;html lang=&quot;en&quot;&gt;<br>…<br>Rest of HTML continued here</pre><p><strong>Notable Finds</strong></p><ol><li>The Set-Cookie header creates a cookie with the key of <strong>eiejmfm-yfgp</strong>, and the value of <strong>iirkb</strong>.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RHGCefrHGksI0qnfm8vmoQ.png" /></figure><p>Given that the title of this challenge is called: <strong>Cops Like Ciphers and Cookies</strong>, this text is not just a random bunch of letters, but a ciphertext. Furthermore, this ciphertext looks quite short and simple, making it likely to be a primitive cipher. Now, we need to figure out what cipher and key was used to decipher this.</p><p>Remember that we saw themindfool.com article before? What was the title again? <strong>consistency is key</strong>. It is likely that the key for this ciphertext is <strong>consistency</strong>. The problem now is that we don’t know what cipher it is using.</p><blockquote><strong>Bonus:</strong> Using a site like: <a href="https://www.boxentriq.com/code-breaking/cipher-identifier.">https://www.boxentriq.com/code-breaking/cipher-identifier.</a> One can detect the likely primitive ciphers that was used. Then, using a site like <a href="https://www.dcode.fr/en,">https://www.dcode.fr/en,</a> one can decode the ciphertext.</blockquote><p>2. While going through the HTML, there is a interesting string found.</p><p>There is a span that contains a class with a long string, which was hidden in the to-do list:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XXOEhSGbLIFEvSFrqrE46Q.png" /></figure><pre>&lt;span class=&quot;dot V2UgbmVlZCBzb21lb25lIHRvIGZpeCAvbG9naW4sIGl0J3MgYmVlbiBicm9rZW4gZm9yIGZhciB0b28gbG9uZy4=&quot;&gt;&lt;/span&gt;</pre><p>This string looks like an encoding format because it ends with an equal sign `=`, which is padding from base64 encoding. There is also a small chance it could be a ciphertext or such, but let’s first check if it is an encoding format since that is much easier to decode.</p><blockquote><strong>Bonus</strong>: If we were uncertain of the encoding format, and couldn’t recognize it was base64, we could check with a site like <a href="https://dencode.com/en/,">https://dencode.com/en/,</a> which would provide results for a wide range of encoding algorithms.</blockquote><p>After decoding the base64 string using the <strong>base64</strong> program from the <strong>coreutils</strong> package:</p><pre>$ echo &quot;V2UgbmVlZCBzb21lb25lIHRvIGZpeCAvbG9naW4sIGl0J3MgYmVlbiBicm9rZW4gZm9yIGZhciB0b28gbG9uZy4=&quot; | base64 - decode<br>We need someone to fix /login, it&#39;s been broken for far too long.</pre><p>We can see an important hint, there is a endpoint <strong>/login</strong> that we can try to visit. This should be our next lead.</p><blockquote><strong>Bonus:</strong> Using a web server scanner like Nikto (https://github.com/sullo/nikto), we can quickly find site vulnerabilities and potential leads. The scanned site looks like the following:</blockquote><pre>$ nikto -h http://challenges.magpiectf.ca:13000<br>- Nikto v2.1.5<br> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<br>+ Target IP: 3.142.244.221<br>+ Target Hostname: challenges.magpiectf.ca<br>+ Target Port: 13000<br>+ Start Time: 2025–02–26 09:39:52 (GMT-7)<br> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<br>+ Server: No banner retrieved<br>+ Cookie eiejmfm-yfgp created without the httponly flag<br>+ Retrieved x-powered-by header: Express<br>+ Server leaks inodes via ETags, header found with file /, fields: 0xW/b04 0x195305f0f63<br>+ The anti-clickjacking X-Frame-Options header is not present.<br>+ Uncommon header &#39;x-content-type-options&#39; found, with contents: nosniff<br>+ Uncommon header &#39;content-security-policy&#39; found, with contents: default-src &#39;none&#39;<br>+ No CGI Directories found (use &#39;-C all&#39; to force check all possible dirs)<br>+ Allowed HTTP Methods: GET, HEAD<br>+ OSVDB-3092: /login/: This might be interesting…<br>+ 6544 items checked: 0 error(s) and 8 item(s) reported on remote host<br>+ End Time: 2025–02–26 09:49:37 (GMT-7) (585 seconds)<br> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<br>+ 1 host(s) tested</pre><blockquote>The results from the Nikto scan show the endpoint /login.</blockquote><blockquote><strong>Bonus:</strong> Furthermore, in future CTF’s, one can consider using a DNS discovery tool like gobuster(https://github.com/OJ/gobuster), combined with a wordlist from SecLists (https://github.com/danielmiessler/SecLists/tree/master/Discovery/DNS). However, in this CTF, brute forcing and discovery tools were not allowed.</blockquote><p><strong>Dead Ends</strong></p><p>An important endpoint to always check on a webpage is <strong>/robots.txt</strong>. Robots.txt is the txt file that implements the robotics exclusion protocol. This means that we can see which endpoints web robotics are not allowed to visit. Commonly in CTF’s, endpoints and clues could be found here.</p><p>However, in the case of this challenge. There was no such endpoint.</p><pre>$ curl -i http://challenges.magpiectf.ca:13000/robots.txt<br>HTTP/1.1 404 Not Found</pre><p>In the webpage, there were other script files: for CSS and JavaScript. The easiest way to view all the URLs that were requested from the web browser is to view the <strong>Network</strong> tab of your web browser.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LqOPOpgfWbOz5u6APFIJqw.png" /></figure><p>Here, we can view through the main.css, style.css, and script.js code to find notable comments, code or clues.</p><p>I will spare you from all the details. The only notable file was the script.js file, which contained a single function: <strong>takeToWebsite</strong>, which is completely unused. The belief is that this file contains no purpose but to emphasize that the website is a very important clue.</p><p>It may not have been very useful, but it’s important to check through all the files for clues.</p><h4>/login Endpoint</h4><p>Upon reaching <a href="http://challenges.magpiectf.ca:13000/login,">http://challenges.magpiectf.ca:13000/login,</a> we are greeted with the page:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1013/1*AcRj1C16cN0hw2Ltfp0LKA.png" /></figure><p>Once again, I like to curl the webpage with the response headers:</p><pre>$ curl -i http://challenges.magpiectf.ca:13000/login<br>HTTP/1.1 200 OK<br>X-Powered-By: Express<br>Accept-Ranges: bytes<br>Cache-Control: public, max-age=0<br>Last-Modified: Sun, 23 Feb 2025 01:14:52 GMT<br>ETag: W/&quot;44c-195305f149c&quot;<br>Content-Type: text/html; charset=UTF-8<br>Content-Length: 1100<br>Date: Fri, 28 Feb 2025 03:05:42 GMT<br>Connection: keep-alive<br>Keep-Alive: timeout=5<br>&lt;!DOCTYPE html&gt;<br>…<br>More HTML</pre><h4>First Impressions</h4><p>So, we can see that there is a login portal for the web page. We can’t interact with the form in the HTML since it is disabled. Furthermore, there is a note to the admin of IT that we were probably not meant to see.</p><p>We can see that the <strong>admin</strong> text in the web page is italicized. This indicates a very important clue. We now know that the admin of this application is likely the superuser.</p><p>Furthermore, there is a note that they are removing cookies from this page. So, now we know two important things:</p><ul><li>The superuser is called admin</li><li>Cookies are a very important step in this CTF</li></ul><p><strong>Dead Ends</strong></p><ol><li>The first thing to do is to see if we can attempt a login with a POST request using a tool like curl.</li></ol><pre>$ curl -X POST http://challenges.magpiectf.ca:13000/login<br>&lt;!DOCTYPE html&gt;<br>&lt;html lang=&quot;en&quot;&gt;<br>&lt;head&gt;<br>&lt;meta charset=&quot;utf-8&quot;&gt;<br>&lt;title&gt;Error&lt;/title&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>&lt;pre&gt;Cannot POST /login&lt;/pre&gt;<br>&lt;/body&gt;<br>&lt;/html&gt;</pre><p>Unfortunately, it seems that posting is not allowed.</p><blockquote>If posting were allowed on this endpoint, we could’ve attempted posts with encodings of application/x-www-form-urlencoded, and various usernames and passwords such as *admin*, and consistency as the key/password.</blockquote><p><strong>Notable Finds</strong></p><p>Upon looking through the webpage, we will find another string of text that is similar to the base64 we found earlier. In the metadata section we can see a new encoding string</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/759/1*J3__TvfeP1gDy8KkoZ08Pg.png" /></figure><p>Once we decode the base64, we can see the following result:</p><pre>$ echo dmlnZW5lcmU= | base64 - decode<br>vigenere</pre><p>It just reads vigenere. So, what is <strong>vigenere</strong>? If you don’t know, google it</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ATd2kLtKmcWQ0hSMUzzfhQ.png" /></figure><p>This is referring to the Vigenère cipher. This would answer one of the questions we had earlier: What was the cipher that was being used to encrypt the cookie? It is Vigenère. Furthermore, we knew from before that the key must be <strong>consistency.</strong> Now that we know the cipher and key that is being used, we can now see what the cookie key and value is saying.</p><p>Using a site like <a href="https://www.dcode.fr/vigenere-cipher,">https://www.dcode.fr/vigenere-cipher,</a> we can input the cipher text and the key.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/988/1*fQVDBqmHrjfB6KjEizcOlA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/987/1*vlxHQT2G-nD-BxQ1j5HVNA.png" /></figure><p>We can see that the cookie key was representing <strong>current-user</strong>. This in itself is fine and not insecure. Plenty of sites happily show their cookies for their current user session, and the value that follows. The security of a session cookie usually lied in the entropy of the session token. A secure session token should be <strong>at least 16 hexadecimal characters</strong>, making it very difficult to guess an active session.</p><p>There are also other session tokens frameworks, a notable protocol that trusts the clients side is <strong>JWT</strong>. However, since they trusting what the client claims they are, the server uses advanced cryptographic functions like <strong>RSA</strong> and <strong>HMAC</strong> with <strong>SHA256</strong> to prevent spoofing of any kind.</p><p>This applications seems to have taken more to a <strong>security by obscurity</strong> approach since they were trying to hide what the cookie was doing. Furthermore, they didn’t do a very good job of it since we now deciphered it. The cookie value indicates that the current user is a guest. Therefore, if we can edit this cookie to something else, we may be able to log in as that user instead.</p><p>The first thing to try is setting the <strong>eiejmfm-yfgp</strong> cookie to <strong>admin</strong>. This however does not do anything. Perhaps the problem is that <strong>admin</strong> needs to be in ciphertext form like the previous value: <strong>iirkb</strong></p><h4>Solution</h4><p>From everything we gathered up to this point, we now have the following information:</p><ul><li>The administrators of this application really likes both ciphers and cookies (from the title of the challenge).</li><li>We discovered a deprecated login page which indicated two hints:</li><li>The <strong>Vinegere cipher</strong> is likely being used.</li><li>The superuser of the application is likely <strong>admin</strong>.</li><li>The homepage indicates that <strong>consistency</strong> is key.</li><li>There exists a cookie with the key and value that was ciphered. Furthermore, we were able to decipher it to be <strong>current-user=guest</strong>.</li><li>setting the cookie <strong>eiejmfm-yfgp=admin</strong> does nothing.</li></ul><p>Putting this all together, we should try to encipher “<strong>admin</strong>”, and then set the cookie to that value.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*_isGppaTXpeix916dJ3_vg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/436/1*kN4cHcMK1o3BUjpHVOAjyQ.png" /></figure><p>So, <strong>crzav</strong> is the value to set to the cookie.</p><p>Using your web browser in developer mode, you can edit the cookie value by double-clicking the value you wish to edit.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/876/1*LTfarEoihpfwvtFha58Tzg.png" /></figure><p>Upon doing so, we wish to see the effects that this cookie would have on all endpoints of the site. If we happen to refresh the page with the new cookies on the homepage: <a href="http://challenges.magpiectf.ca:13000,">http://challenges.magpiectf.ca:13000,</a> we will notice that the cookie value will reset back to <strong>iirkb</strong>, and nothing occurs.</p><p>Now trying the <strong>/login</strong> endpoint instead with the new cookie. We will get a new page shown to us:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/1*n07DFl3qKabl84UISWRwFA.png" /></figure><p>We now see the flag displayed on the screen, with a little story for the detective hunt. Congratulations!</p><p><strong>magpieCTF{wh3r3_w4s_Jake}</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9f2e4d640532" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making Reading Enjoyable: My Tips for Reading]]></title>
            <link>https://medium.com/@allankong/making-reading-enjoyable-my-tips-for-reading-5be39c715466?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/5be39c715466</guid>
            <category><![CDATA[read]]></category>
            <category><![CDATA[reading]]></category>
            <category><![CDATA[self-improvement]]></category>
            <category><![CDATA[books]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Mon, 24 Feb 2025 05:43:44 GMT</pubDate>
            <atom:updated>2025-02-24T05:43:44.373Z</atom:updated>
            <content:encoded><![CDATA[<p>I used to hate reading, a lot. For the life of me, I could not sit down to read. I loathed it. In school, there were classes where we had to read in groups, and to me, books looked like a jumble of letters that displayed no meaning.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/139/1*oDO45ZTqKkCqAlQhtMdldQ.png" /><figcaption><a href="https://what-if.xkcd.com/76/">https://what-if.xkcd.com/76/</a></figcaption></figure><p>But through a lot of continuous effort, I now read for an hour daily, finishing at least three textbooks a year and a fiction book every month.</p><p>I will have this article split into three parts to save you time:</p><ol><li>Why reading matters (A LOT)!</li><li>Mistakes I made getting started</li><li>My tips to make the most of your reading!</li></ol><h3><strong>Why Reading Matters (A Lot!)</strong></h3><p>My initial goal for reading was to improve my experience as a software engineer (or developer). Near the start of university, I learned that the only way to improve my software skills (besides just coding) was to understand the foundations of software.</p><p>I’ve had a few shares of online courses I went through in high school, the best ones being on edX. But I quickly realized books were usually jam-packed with much more information than any other resource. Text is one of the most compressed forms of knowledge for the brain to dissect, like raw information for us to consume. So, for the sake of improving my skill set, reading was a priority.</p><p>Furthermore, some companies like Amazon require a heavy amount of reading. Mentioned from the Amazon Way by John Rossman:</p><ul><li>“If you needed to explain a new feature or investment to the S-Team or Jeff himself, you began by writing a five-to-seven-page essay… Then, at the beginning of the meeting, you would pass out this narrative and sit quietly for ten minutes while everyone read it”</li></ul><p>So, reading is one of the best ways to dissect information, allowing one to dive deeper into the fine-grain details, and even Jeff Bezos agrees.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/431/1*uVk0CuLvr0XRDWN47tBU_A.png" /><figcaption><a href="https://xkcd.com/365/">https://xkcd.com/365/</a></figcaption></figure><p>The problem was, I sucked at it.</p><p>Not only did I suck at reading non-fiction, but there was also the side of fiction books. I’ve always wanted to be a sophisticated person; someone who reads classic books. I have barely read any fiction books, and I felt like a complete imbecile in culture. I couldn’t discuss any cool books like 1984, Frankenstein, etc. I thought fiction books were only for younger audiences, or suited for posh individuals, with little real practicality. I mean, why read a fiction book when I could be learning about software?</p><p>However, I’ve seen scientific proof that reading fiction books can do wonders for the mind:</p><ul><li>It can improve social cognition (<a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4733342/">https://pmc.ncbi.nlm.nih.gov/articles/PMC4733342/</a>). This can be seen as vital for a job setting, where we deal with managers and coworkers.</li><li>Reading can improve stress levels, reducing them by over 68% (Lewis, D. (2009), Galaxy Stress Research. Mindlab International, Sussex University, UK.)</li></ul><p>Now, there are other things that I think that reading does, but I have no sources to back me on this, so pretend like it is all true. Yep:</p><ul><li>Improves memory</li><li>Helps sleep</li><li>Preventing cognitive decline</li><li>Making you live forever</li></ul><p>So, I hope I got you all convinced of the power of reading and the wonders it can do for you: both career and health-wise.</p><h3><strong>Mistakes I made Getting Started</strong></h3><p>I wanted to make reading a habit for learning software, so starting I tried to pick up a heavy textbook.</p><p>It was painful.</p><p>I got bored, frustrated, and tired. Most of the time, I couldn’t bother anymore. I had the same issues with fiction books too.</p><p>So, I want to share the biggest mistakes I made so you can avoid them yourself.</p><h4>Starting too Big</h4><p>I think the biggest mistake I made was trying to get into hard reads right off the bat. I had a few classic books lying around and wanted to get into it. I picked some of them up, like Sherlock Holmes (A Study in Scarlet). Man, it was a tough read. It makes it harder to get into a habit when reading something complicated and foreign like that.</p><p>Furthermore, on the side of non-fiction, there is a large range of difficulties in textbooks. Some texts read as if it were a fine print with the blandest possible information, while others can be descriptive yet interesting and throw in jokes here and there.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/597/1*CKD2OlTfSJ7_3W3ekwQa3g.png" /></figure><p>Remember that there is a range of difficulties in any book genre. Some will be a lot easier to read than other. Don’t be afraid to start too simple, it’s important that your reading journey starts with ease. This leads to my next mistake.</p><h4>Reading Things that were Boring</h4><p>I started off reading simply to learn. I didn’t find the process that engaging or interesting.</p><p>It was more of a chore, quite like being forced to show up to lectures at that one mandatory university class that you hate.</p><p>I was embarrassed to read stuff like Harry Potter, or Hunger Games, thinking that they were just for teenagers, and that I was past the age for stuff like that. But, once I started on those series, it led to my passion for reading in general. Sometimes you need something to get you into reading, start with something simple and interesting, and then you can naturally find yourself reading more complex works.</p><p>In addition, for textbooks, sometimes I would choose textbooks that aren’t the most concise and detailed in favor of more interesting reads. This is a bit debatable, but I enjoyed reading <a href="https://beej.us/guide/">Beej’s Guides</a> (For C, networks, and network programming), even though there are a few syntax errors and outdatedness in the C code. I did this since Beej’s writing style was simply more interesting to me and allowed me to dissect much more content. The errors in the textbook were minimal, and I always resolved to other resources for more details anyhow.</p><p>In addition, find yourself some other ways to enjoy reading. I’ve never done so myself, but reading with audiobooks can do wonders for others.</p><h4>Forcing Myself to Understand Everything</h4><p>I will start with the fiction side of things. When I started reading “100 Years of Solitude,” characters and events started leaking out of my mind. What made it even more confusing was that some characters have the same names, and there are at least 15 of them.</p><p>At first, I reread sections that I didn’t get, or if I forgot something, I would search through the book. I wanted more than just reading a book, but to dissect all its details. Soon, I realized that maybe the author intended for you to flow through the book like one does through life, forgetting the fine details but recalling vague memories. So, I stopped feeling the pressure to understand every little thing and just went with the flow of the story.</p><p>Furthermore, it’s fine to use sites like SparkNotes to help understand the plot, deeper meanings, or whatnot. There is not a single defined way to enjoy books. Do it however you like!</p><p>On the side of non-fiction books, please don’t force yourself to get a concept that is too hard or complex. When I read through textbooks and don’t understand a concept, I would typically reread a section or seek an alternative resource like Wikipedia. By then, I would understand the concept and move on. However, there were times when I reached things beyond my grasp, and I would let it be a roadblock.</p><p>Don’t.</p><p>Feel free to skip things, maybe it will make sense when you finish a later chapter and go back to it. The structure of a book is usually a great guide, but sometimes you must bushwack.</p><h4>Buying Paperback Books</h4><p>Books are expensive. Try to find ways to mitigate that cost, like going to the library.</p><p>The best investment I’ve made was a Kindle;, books were so much cheaper this way. Utilizing e-book subscriptions, one can save a ton of money.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/975/1*IWBTVyhoek145Y4pXRMi1g.png" /><figcaption><a href="https://xkcd.com/294/">https://xkcd.com/294/</a></figcaption></figure><p>Furthermore, there are sites that provide e-books for free. My goodness, shame on them. The way these sites do so is none of my business… you should not investigate this as an option yourself, especially for textbooks that cost $80 for no reason whatsoever. Don’t consider it 😏</p><h3><strong>Making the Most of your Reading!</strong></h3><p>So, at this point, I’m going to explain things I like to do as I read that make my life more fun and interesting whilst reading.</p><h4>Not being Afraid to Skim Things</h4><p>Sometimes chapters can be boring.</p><p>This applies to both fiction and non-fiction.</p><p>Some chapters in fiction books can just be completely removed without impact on the story. Am I suggesting to totally skip these chapters? No. I’m saying that you don’t need to read it in the finest detail as one would with the other parts of the story. Now, here is the hard part:, how do you know what part of the story to skim? Well, for me, the best metric is how fast my brain is shutting down from the text I am reading. But sometimes this can be confused as being tired in general, and in need of a break.</p><p>Some textbooks contain chapters that are copied and pasted texts from documentation, which are so detailed that if one were to dissect it all, you would waste your entire reading session on 2 pages. The best metric for determining whether you should skim a section is judging whether you will remember the details you are currently reading. Of course, this is completely dependent on the person since some details may be more interesting to you. Furthermore, sometimes there are things that one should not skim if it were essential to understanding the textbook. Skimming is less about skipping the high-level concepts of a book, but skipping the extremely low-level details, such as specifications, implementation details (at times), and history (I can’t remember the detailed history of technologies, and why should I?).</p><h4>Balance Fiction and Non-Fiction</h4><p>At first, I started with reading only textbooks. It worked and I got quite good at it. But I find that reading with a balance of 50% fiction and 50% non-fiction split is much better for me.</p><p>I am typically able to read much faster since I have more things to look forward to when reading (since either book could be exciting). In addition, I treat reading fiction as a break. It helps my mind relax and let concepts refresh itself in my unconscious mind.</p><p>One thing to note is that the split of 50/50 fiction and non-fiction also depends on how difficult the fiction book is. If the fiction book were an old English classic, then it would be mentally straining to read, and I would even start to view it as a bit more of a non-fiction book in a sense (because of the mental energy it takes to read). So, one could think it’s less about fiction and non-fiction, but the difficulty of the reads, and the need to balance it to ensure better rest and comprehension.</p><h4>Refreshing Your Mind</h4><p>I find this tip to apply more to non-fiction books: ensure that you understand what you’ve read.</p><p>After a chapter, you should be able to summarize the chapter relatively succinctly. In addition, if anyone were to ask you any questions about the book or topic it was covering, would you be able to provide a detailed enough response?</p><p>The number of details you want to consider is up to you, if you are not satisfied, either reread the section or find another resource that explains the concepts better. Of course, don’t try to get hung up on every detail.</p><h4>Keeping Yourself Motivated</h4><p>Whilst reading something complex or large — for me, an example was “How Linux Works 3rd Edition” — it can be daunting with how many small details there are to cover. I mentioned skimming earlier, but sometimes one must just push through and read the details.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/450/1*A7azTwnfNiCdtBt7mm5lpg.png" /></figure><p>I have two methods for detailing with motivating on a heavy read:</p><p>The first is rewarding oneself. After having completed a chapter, you can do something exciting with the information you’ve read. Talk to someone else about what you’ve read or go online to talk about it. If it is a textbook with exercises, you can also do some practice. If it is a fiction book with a movie, think about watching it after reading the novel.</p><p>The second is a “purpose refresher”. What was the purpose of reading this book? Sometimes after so many chapters of a book, especially mundane ones, one easily forgets why they were reading in the first place. Rethink why you are reading the book and think about the skills or knowledge gained from finishing it. Before I read a book, I like to look at the table of contents and think about what I will do with all the new skills I will gain; it gives me the strength to finish through some hard chapters.</p><p>But, if this does not work, it leads to my next point</p><h4>Don’t be Afraid to Drop a Book!</h4><p>Sometimes a read is just not interesting, too heavy, or too complicated. That’s okay. You should not feel pressured to finish a book; it’s not a blood contract. Also, maybe you can finish in the future!</p><h3><strong>Conclusion</strong></h3><p>I hope I shared with you the beauty of reading and got you all hooked. Obviously, if you made it to the end of this article, you are already a capable reader. I hope the tips were still useful regardless!</p><p>Happy reading!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/583/1*3EZnf4Heor9dR7oVwdkNuw.png" /><figcaption><a href="https://what-if.xkcd.com/76/">https://what-if.xkcd.com/76/</a></figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5be39c715466" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Study Abroad: Oxford Brookes University vs University of Calgary]]></title>
            <link>https://medium.com/@allankong/study-abroad-oxford-brookes-vs-university-of-calgary-ecc34764a975?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/ecc34764a975</guid>
            <category><![CDATA[study-abroad]]></category>
            <category><![CDATA[university-of-calgary]]></category>
            <category><![CDATA[oxford-brookes]]></category>
            <category><![CDATA[oxford]]></category>
            <category><![CDATA[study-exchange-program]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Thu, 06 Feb 2025 23:59:05 GMT</pubDate>
            <atom:updated>2025-02-07T00:02:30.267Z</atom:updated>
            <content:encoded><![CDATA[<p>I have just finished a 4-month long study abroad program to Oxford Brookes University offered by my university: University of Calgary. To say the least, I felt like my mind was being teared a new one every day and I loved it. I’ve never been to anywhere in Europe before, and the UK was the first country I landed in. While in Oxford, I was introduced to beautiful architecture, delicious food, and fun British culture.</p><p>But this isn’t an article about how amazing Oxford, or the UK is, it’s about Oxford Brookes University and the University of Calgary.</p><p>I’m going to compare my experiences between my host university in Canada and Oxford Brookes University in the UK.</p><p>First off, I do want to mention that I was scared of the UK at first. I did have the idea that the Brits would be talking like Paddington Bear and be incomprehensible. Perhaps people would talk to me with such an accent that it would sound like a different language entirely. But I am very thankful that it didn’t turn out as I feared at all. Yes, there was slang here and there that I had to pick up, but 95% of the time, I understood the accents of the people in Oxford.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/975/1*MlQEtIvmP5d8yMn8D2ER_w.png" /><figcaption>Canadian not smiling initially because he was scared of the UK</figcaption></figure><h4><strong>Culture</strong></h4><p>The biggest thing that shocked me, and that I now love, is the fact that there are two casual boozers on the university campus, the Brookes Bar and the Sports Bar. The pints go for a cheap price, at only £3.00. I love the fact that a university would support the drinking life, something that could only happen in Britain of course! I made some great mates in Oxford, and we would meet up at one of the pubs and drink — and you could hang out without drinking as well. At the University of Calgary, there are two <strong>bars: </strong>The Den, and The Last Defence Lounge. They are both great locations and are part of the SU and the Grad Students Association. However, they have more of a restaurant atmosphere, so they feel less like a casual hangout space (but there are more food options).</p><p>Furthermore, I find it a lot harder to convince mates in Calgary to come over to the pub. But, at Brookes, I found that people were always down to hangout at one. This is not just a Brookes thing, I know, everyone in the UK loves drinking. I’ve met some mates who would regularly go to spoons (Wetherspoons) for some cider and such, and it is a great way to have fun. In Canada, it’s much harder to find people who want to just hang out at a casual spot.</p><p>I found the relationship between the instructors and students much more relaxed. At Brookes, students would address the instructor usually by their first name. People would walk up to their instructors in classes and just have conversations with them. I recall a time a professor “joked” about pirating our textbooks since they are so pricy (for legal reasons I will not elaborate), something that would usually only happen between mates. At times, I would see some of my instructors at “The Forum” among students. There are even academic advisors who have regular meetings with you about grades, life and such. It’s very nice to have such a personalized experience. I had an amazing academic advisor who took me and a friend out to a pub and bought us drinks. Yes, you read that right Canadians. I couldn’t have imagined a world where an <em>academic </em>advisor would buy <em>students </em>drinks!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/244/1*PMFf246FXn0dzHGzoAEoIQ.png" /><figcaption>Enjoying a ½ pint</figcaption></figure><p>Meanwhile in Canada, there is a very heavy distinction between a professor’s professional and personal lives. Students usually address professors by their last name, and with a title too. Of course, students can also be mates with their professors, but usually this is a lot rarer. Mainly research students get close to their professors, since not only is it hard to talk to a professor, but classrooms can be upwards of 300 people. Standing out amongst the crowd is a bit tricky there.</p><p>Comparing academic advisors, U of C does provide a lot of academic support. Students book meetings online with a select group of advisors, with the chance of speaking to a new person each time. I find that it is hard to keep track of all the services that U of C provides. Of course, academic advising is a lot more complex in Canada due to the more flexible degree programmes.</p><p>So, in terms of culture, I think hanging out at the pub makes everything more fun, and its easy to be friends with instructors and advisors.</p><h4><strong>Student Life</strong></h4><p>I think this is a very difficult section to touch because Oxford is just a beautiful and dense city, while Calgary is a bit more on the bland, suburban side. But I digress…</p><p>The Oxford Brookes Students’ Union holds a generous number of events. There was an ABBA Bingo event, Cricket at Sixes’ Cricket Club, and Darts at Flight Club. I found these events to be great and well worth the small fees of ~£5. Personally, I do wish that they held more events like these, but at least they were of very high quality.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/710/0*OUCedtrU_-zVBOSB" /><figcaption>Cricket Event at Sixes’ Cricket Club</figcaption></figure><p>I found the students societies (called clubs in Canada) to be a bit lackluster at Brookes. There weren’t as many societies hosting frequent events. One time, the Jazz and Christian society collaborated on a wine and cheese night. The cheese provided was quite nice. But, as I am in Computer Science, I really wished there was a computing society, and just more club events in general. At least “The Guild” had regular board game meetings that I heard were very nice. In addition, Brookes International Student Advice team had very cool events. I would buy some tickets for day trips to nearby locations, such as Stratford, Cardiff, and Cambridge. It was very kind of them to organize those trips.</p><p>In Canada, I would say that the university and students’ union do not provide many fun activities. Just looking at the website, I see a bunch of stuff regarding academic advising: <a href="https://events.ucalgary.ca">https://events.ucalgary.ca</a>. It’s just not very exciting stuff:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/451/1*02eanCFhVVbXR25tqiBbsQ.png" /><figcaption>Example of a U of C Event</figcaption></figure><p>But, while these events are boring, we have many clubs (reminder that clubs = societies). <a href="https://suuofc.campuslabs.ca/engage/organizations">https://suuofc.campuslabs.ca/engage/organizations</a>. Our listing of clubs reaches 290. There are over 7 clubs related to computer science alone. Despite all these clubs, it can be hard to find events posted by the clubs since they all use their Instagram for marketing, and there is no centralised location for searching for events.</p><h4>Classes</h4><p>In a nutshell, Brookes focuses more on the practical hands-on aspect of software development. The classes I took were Secure Programming, Malware Analysis, Foundations of Security, and Introduction to C and C++. My favourite of them being malware and secure programming. Each class tried to focus on practical problems that occur or occurred in the real world. To reinforce our learning, there would be a practical session which went over example problems such as performing a buffer overflow attack, arc injection, or using Wireshark. These practicals would usually be led by the instructor. Whilst in Calgary, we would have Teaching Assistants (hired students) to instruct these practicals. Doing the Brookes practicals with Ian Bayley (a quiz celebrity featured on Mastermind and other British shows), was quite educational and fun. On the other hand, some of these practicals were less interesting (Brookes students can take a guess which class that was).</p><p>At University of Calgary, I feel that we touch more on the fundamentals of computing. We do subjects like Theory of Computing, Algorithms, Programming Paradigms, and such. Now, I do enjoy these classes quite a lot. But the practicality of these courses are far less obvious than something as direct as Malware Analysis. I’ve heard great things about the Networking course at Brookes, which involves physical subnets and routers. At University of Calgary, the equivalent course mainly has a textbook where we read about the underlying protocols without having touching a real network.</p><p>I find a balance between the practical and foundational knowledge of software important, and I think that the University of Calgary has a bit to learn about doing more hands-on classes. But it’s not useful to compare the two universities since they are focused on different outcomes: one to get practical experience, the other to prepare you to be a computer scientist.</p><p>I did find the workload at Brookes to be laxer. There was typically only a maximum of two assignments per course, and a final exam which was worth a good chunk of your grade, perhaps 50%. These assignments were not too tricky but usually took a good amount of time, focused on making students do a project. Compared to Calgary, we have many assignments to do, perhaps 1–3 a month per course. These assignments would range from projects to making toy programs. The latter being much more common.</p><p>But an important thing to consider is that an A+ at Brookes is 75%. Despite this, I found the coursework to be graded quite leniently, and it’s quite uncommon to fail a course from what I’ve seen. At Calgary, it is course dependent, but the minimum for an A+ is typically 95%.</p><p>My favorite part of classes at Brookes is that there are “presentations” you do to your grader. These are not real presentations in a sense, but questions to ensure that the work you did is your own and that you actually knew what you were doing. Most my classes required a meeting where I discussed my work and the thought process behind it. I see the merit behind it, to catch cheaters and such.</p><p>I think that UCalgary has a bit to learn when it comes to catching cheaters. Since our coursework is most of our grade, some students get by through cheating on assignments despite bombing tests.</p><p>At UCalgary, it felt like courses and grades were less standardised. Sometimes, I would have to contest grades. But I think it could have been that I’ve been at UCalgary for much longer than I was at Brookes.</p><p>On the side of Brookes, I do think that there is a bit too much time dedicated to assignments. There would be a week of class dedicated to the assignment, questions for the assignment, and another week with no classes to work on these assignments. But, honestly, it’s quite nice to have so much free time to do whatever I want.</p><h4>Campus</h4><p>The campus at Brookes is much smaller than UCalgary. But it gives off a very cozy feeling. I enjoy how there are always changes to the front desk. When I was there, there were some Lego builds of different landmarks. I found it very cute.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4blJLmToU4pXZ_aQ" /><figcaption>A Cute “Books Not Brookes” Christmas Tree</figcaption></figure><p>On the outside, I quite liked the metal structure that looked like upside-down umbrellas. At night, it would light up and look very aesthetic. Not to mention, the CO-OP store on campus is very nice. Many students would get their lunch meal deals from there. Buying a CO-OP membership is a must, since it is only £1 and you can get £1 off your shop almost weekly.</p><p>My favorite location on campus was “The Deli.” The lunches would be quite cheap: £5.50 and very filling. The meals would rotate every day. My personal favorites would be the Christmas turkey dinner with stuffing and mash. There was also a delicious Yorkshire pudding wrap, the best I’ve had in the UK.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DhYqWYxhrWkXH_kg" /><figcaption>A meal from The Deli for £5.50 + £1.50 Spring Rolls</figcaption></figure><p>I very much enjoy Calgary’s campus as well. There are many different services provided by the University. Since there are so many things here on campus, I will just list them:</p><ul><li>A campus food hub that has cheap groceries, and soups on Wednesday for $2.00.</li><li>A food court for students called MacHall. It is filled with restaurants.</li><li>Free tea and fruit provided by the Life Design Hub</li><li>13 public squash courts.</li><li>The Den (mentioned before) has a subsided meal for only $3.</li></ul><h4>Student Accommodations</h4><p>At Brookes, I was living in Clive Booth with some amazing mates. Though, I have heard some horror stories about flatmates who would never clean the kitchen 💀. First off, my favorite thing about the residence is the kettle. It boils so fast! Okay, moving on, that had nothing to do with Brookes. I found the Brookes campus services to be very swift and effective. Whenever we filed in a problem about our residence, they would come within a few days and fix it. Honestly, residence was quite standard. I think the only problem we faced was freezer space being limited since students live off frozen food. But everyone had ample storage space, with 2 cupboards per person.</p><p>In addition, sometimes there would be loud English banter outside. Whenever it was noisy past 11pm and we called campus services, they were very swift to stop the sound. It would take 10–15 minutes for them to address the sound, which is quite quick compared to CA response times at UCalgary.</p><p>Basically, I’m very thankful that Brookes has provided us a swift and efficient service. I have heard mixed experiences from other people, so it’s hard to give an objective conclusion.</p><h4>City Life</h4><p>As a nice bonus section, let’s turn to the city aspect. Let me quickly talk about Calgary:</p><ul><li>There is a nice big public library called Central Library</li><li>A music museum called Studio Bell</li><li>A lot of parks to walk around, the biggest being Nose Hill Park</li><li>Nice communities with shops like Inglewood and Kensington</li><li>Theatres and auditoriums, though usually quite expensive to attend</li><li>Calgary Stampede (the biggest in the world!)</li><li>A lot of big malls</li></ul><p>Okay, now I’m going to talk about Oxford:</p><ul><li>Norrington room at Blackwells. Best place to read and indulge yourself!</li><li>Oxford theatres. There are a lot of shows and musicals to watch at a low price. I loved New Oxford Theatre and Oxford Playhouse</li><li><strong>Completely Free </strong>Museums, my favourites being: Pitt Rivers and the Ashmolean.</li><li>Covered Market: love all the food there</li><li>Free and very festive Christmas markets</li><li>Visiting the Oxford Colleges and Bodleian Library</li><li>Westgate Mall (much smaller than Calgary malls, but it looks nice)</li><li>Pigeons</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/533/0*N1mzilroCa6c9-Gn" /><figcaption>Watching West End “Dear Evan Hanson” for only £20 at New Theatre</figcaption></figure><h4>Recap</h4><p>Basically, hanging out at pubs makes life more fun, Brookes’ courses are more hands-on, and there’s more opportunities for direct and friendly interactions with instructors in the UK.</p><p>I really enjoyed my time there and will cherish it forever ❤️.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/533/0*H4VmsVsjKwm6N-4z" /><figcaption>Photo with local law enforcement</figcaption></figure><p>Come over to visit UCalgary too if you have the chance, it may be studious, but it is quite beautiful! And, we have quite a large campus for you to explore!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ecc34764a975" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I’ve Analyzed Over 2498 Medium Articles: What makes a Good Title?]]></title>
            <link>https://medium.com/@allankong/ive-analyzed-over-2498-medium-articles-what-makes-a-good-title-fe189ba7cfb0?source=rss-8d916fe51be8------2</link>
            <guid isPermaLink="false">https://medium.com/p/fe189ba7cfb0</guid>
            <category><![CDATA[naturallanguageprocessing]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[writing-tips]]></category>
            <category><![CDATA[medium]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Allan Kong]]></dc:creator>
            <pubDate>Sun, 28 Apr 2024 18:37:11 GMT</pubDate>
            <atom:updated>2024-04-28T18:37:11.738Z</atom:updated>
            <content:encoded><![CDATA[<p>I will try my best to make the process simple, yet still descriptive for all viewers.</p><h3>Links</h3><p>If you want to see my full technical report, it is visible here: <a href="https://drive.google.com/file/d/1QzmXUsx6rVOt9m1obQOGDFTs6xN7gAfp/view?usp=sharing">Full Technical Report</a></p><p>The notebook file can be seen here: <a href="https://colab.research.google.com/drive/1lYsfuyqTT4LDNH4zHI1h_yhlAC2J1lI-?usp=sharing">Google Colab Notebook File</a></p><h3>Introduction</h3><p>In this project, I utilized a dataset from Kaggle, the <a href="https://www.kaggle.com/datasets/arnabchaki/medium-articles-dataset">Medium Articles Dataset 📝</a>, which spans from January 2023 to March 2023, containing 2498 articles. I dissected various features of article titles and determined which feature lead to better user interest, which was measured by claps.</p><h3>Title Focus and Topic</h3><p>The genre of what you are talking about seems to make the largest difference in the user interest. Utlizing BERTopic, it was determined the best performing topic was those that were focused on finance, passive income, and such. Articles in that category would score with an average of 1653 claps. Some examples of those titles are as follows:</p><blockquote>5–9 years of obsession will save you 5 decades of working a 9–5.</blockquote><blockquote>I quit my 6-figure job once I learned 5 unpopular things.</blockquote><p>In addition to this, I charted words with their average clap, to find the most important words in article titles.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*OM2gfSKcPsuxhWTBZ_Un4g.png" /></figure><p>We can see that notable words that show up are: “$350”, “$0”, “passive”, “luxury”, “employable”, and such. This shows that the kind of articles that garner the most claps from users are those of lifestyle, personal finance, and income.</p><p>To further support this, having a “$” dollar sign in the article title shows an average difference of claps of 802.17.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*8IRTFoPwLocYyiedLlKY9w.png" /></figure><p>So, if it is your cup of tea, try to make your articles more garnered towards finance and income, or add a dollar sign. Of course, sometimes this is not possible and could be considered a little scummy if that’s not what you want to write about. We will move on to the more pleasant features now.</p><h3>Article Length</h3><p>A good article length would be within a unit of standard deviation. Hence, the best character length for an article title would be between the range of 36–73 characters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/584/1*SoiAu9C7qzBmDHPKDhMNgg.png" /></figure><p>The ideal number of words in a title would be between the range of 6–12 words.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*vxlMVGGyVC0dazw0MBgGMA.png" /></figure><p>However, keep in mind that there is not a very high Pearson correlation (correlation in general) between the article claps and the length of an article title, hence it is not worth worrying about the article title length. You can still have a smash-hit article with a very short length.</p><h3>Reading Ease</h3><p>This feature seemed to matter an extremely large amount. Reading ease was calculated with the Flesch reading ease score, which measures the school reading level of the given text. It is calculated with the following formula:</p><blockquote><em>206.835–1.015 x (total words / total sentences) — 84.6 x (total syllables / total words)</em></blockquote><p>The formula aims to find how complex your words are based on the syllable usage in your sentences and words.</p><p>I graphed the correlation between reading ease and claps, which can be seen below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/586/1*U_0wlYzLisL1kv4FYzIOuA.png" /></figure><p>Those with a lower school reading level correlated to much higher clapped articles. The correlation between reading ease and claps is linear and has the second highest Pearson correlation.</p><p>The best reading level for articles seemed to be 5th grade. So, unless your writing style is very articulate, try to avoid using too many complex words and keep things simple in your article titles.</p><h3>Number of Numerals</h3><p>If possible, try to use numeral forms instead of the number word, for example: “2”, instead of “two”. The number of numerals in an article title shows another strong correlation to claps.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*lvCXRxpIlJ3aebnT-TiUeA.png" /></figure><p>Number of numerals has the highest Pearson correlation to claps, at 0.23. So, the number of numerals you add do represent better claps. I would suggest that you try to aim for at least 5 numbers in your title.</p><h3>Parts of Speech</h3><p>Article titles that contain easier to read language and morphology will perform better as Medium articles. It is seen that with an increase of nouns, there is a decrease of claps. This makes sense as too many topics in a title can be confusing and lead to a more convoluted article.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/571/1*dUtB6rUkQwtgMi_yfvCzKg.png" /></figure><p>Try to keep the focus of your title clear and easy to comprehend. You can do this by not having too many verbs or nouns going on, make the focus of your article titles crystal clear.</p><h3>Best Phrases</h3><p>I found the most important phrases of length 2, 3 and 4 words long. There isn’t too much to say here, so I will just show the plots:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/1*k621JHngcJlyJa-Blsv8Lw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*p_nmfypjkL6eHf68WCHMsg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/609/1*k8HpbClMyxGkWpLOyyULqQ.png" /></figure><p>As you can see, a lot of the phrases are very specific to finance and such, in addition, it is susceptible to outliers in the dataset.</p><h3>Issues</h3><p>To test the correlation between features and the importance of certain features, I trained a random forest regressor model. However, it did not perform very well, with a very low R-Squared Error: -0.034. The likely reasoning for this is that there is little to no correlation between article titles and claps.</p><p>There are various external factors that influence the number of claps on an article. For example, having a publication can drastically alter the number of claps received.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/917/1*n81RD0rsCZX9o7YuB_By4g.png" /></figure><p>Furthermore, being a famous writer on Medium will grant you a larger audience of people, and a higher chance to get claps despite how poorly written your title could be.</p><p>In addition, this database was quite small, with only 2498 rows. Perhaps with more data, we can better understand what the Medium platform’s trends are.</p><p>In essence, sometimes, the title of your Medium article doesn’t really matter all that much in the end. If you wanted to reach out to a greater audience, or get more claps, you should look into a publication or marketing.</p><h3>Summary</h3><p>Try to keep your articles in the range of 36–73 characters or 6–12 words. Make the article title as easy to read as possible, ideally 5th grade level (even a 5th grade student can read it). Try to use numeral numbers instead of the word form whenever possible (“1” instead of “one”). Keep the number of nouns low, so that the article title is coherent. If you can, maybe use one of the phrases from the graphs above, only if it suits your article already, however. Finally, remember that article titles don’t always mean more user retention, sometimes it’s just a game of luck and marketing.</p><p>Thanks for reading and let me know what you think in the comments below, and clap the article if it was helpful!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fe189ba7cfb0" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>