Haskell Advent of Code progress

I finally rediscovered the delight that is writing haskell code. At the start of the week I started solving simple exercism exercises, but that got boring quickly. (Btw I finally 100%-ed the rust track on exercism again, yay 🎉🎉) Later in the week I also rediscovered my started AoC2023 attempt so I switched over from exercism to continuing it.

The first half of day 10 was already solved but at the time I was too stressed about the second half and decided to stop and to enjoy advent with the family. Turns out, the second half of that task wasn't too difficult. I just needed to turn the results from the first half into some visuals, which worked pretty fast.

Day 11 was a bit trickier and I spent quiet a few hours solving it. I wasn't as happy with my solution there as it seemed kind of messy. I also had to debug quiet a bit since I ran into the trap of foldr vs foldl yet again. A haskell newbie like me tends to think of both of them as replaceable. I already learned that foldr is better for lazy evaluation as long as f is non strict (usefull for non-terminating sequences) and foldl is in turn better for strict evaluation. But I forgot about the fact that the associativity of f also plays a role. I always tend to think of the example implementation of sum when I try to visualize any fold function, which is misleading since (+) is associative. In the implementation of day 11 I used a non-associative f which lead to the wrong outcome. Anyways, I learned something and that's why I'm doing it in the first place so that was the perfect outcome I guess.

Configuring haskell-tools for neovim and other LSP improvements

I found a similar plugin to rust-tools for haskell, namely haskell-tools. It wasn't that eay to set up on NixOS. Half of the cool features didn't work unfortunately :/ I didn't know there was a hoogle CLI-tool, but that's apparently required for some functionality of the plugin. hoogle however, wasn't running at all since I got some weird HTTP timeouts when trying to download the hoogle db.

Other than that I also updated some general configuration parts of the general nvim-lspconfig part of the config. This includes fancy new keymaps which use <space> as a modifier key. This finally gives me back some key combinations to map to.

Weekly Learning: The Beauty of Clear Code

Feel free to contact me via email if you want me to take this content down!

Excerpt from the insightful book A Philosophy of Software Design (Chapter 18)

In the realm of software development, there's a common challenge known as obscurity. It's when vital information about the software remains hidden from new developers. But fear not, for there's a powerful solution: writing code that is abundantly clear. Yes, the key is to make our code easily understandable, not just for ourselves but for anyone who reads it. While it's often easier to spot unclear elements in others' code, we can harness the power of code reviews to find these hidden issues in our own creations. By doing so, we not only improve our code, but we also cultivate the habit of writing clear code from the very beginning.

Things that make code more obvious

Let's explore two essential factors that contribute to code clarity:

  • The Power of Good Names (link coming soon): Choosing meaningful names for variables, functions, and more can work wonders. Clear names eliminate the need for excessive documentation and help readers quickly understand the code's behavior. On the other hand, vague names force readers to spend extra time deciphering their meaning from the surrounding context. Let's save everyone's time and effort by using explicit names.

  • The Beauty of Consistency (link coming soon): Consistency in our code brings a sense of harmony. When we follow consistent patterns and approaches, readers can navigate through the code more easily. By establishing a coherent structure, we help readers make faster and more accurate conclusions without extensive analysis.

Things that make code less obvious

However, there are certain factors that can cloud code clarity:

  • Beware of Generic Containers: Generic containers, especially tuples, can sometimes obscure the meaning of our code. Tuples lack explicit field names, leaving readers to guess the intention of each component. To improve clarity, it's advisable to favor the use of struct instead of tuples, particularly when cleaning up our code.

Key Takeaways for Code Clarity

Let's remember these essential principles for crafting clear code:

  • software should be designed for the ease of reading, not the ease of writing : When we write code, it's important to keep in mind that its primary audience is not just the computer executing the instructions, but also the human developers who will read, maintain, and build upon that code. Prioritizing readability means making our code clear, concise, and easy to comprehend. It involves using meaningful variable and function names, organizing code in a logical manner, and applying consistent formatting and style conventions. By placing readability at the forefront of our coding practices, we ensure that our code becomes a joy to work with for both ourselves and our fellow developers.

  • If a piece of code cannot be grasped at a glance, it's a red flag indicating that important information is missing for the reader. Embrace this signal and strive for clarity : Code should communicate its purpose and functionality effectively, even upon a quick glance. If we find ourselves struggling to understand a code snippet or if it requires significant effort to comprehend its meaning, it's a warning sign that something is amiss. It suggests that vital information is missing, such as clear variable names, comments, or documentation, which are essential for understanding the code's intent. Instead of brushing aside this red flag, we should embrace it as an opportunity to enhance clarity. By adding meaningful comments, refining variable names, or breaking down complex logic into smaller, more digestible parts, we can ensure that our code is readily understandable to anyone who encounters it.

Ideas on a bevy design workflow

I just a some thoughts on a general workflow in bevy to organize the way to write new code. Should help to create better code on "the first iteration". It is the following plan:

  1. Start by scaffolding a new plugin or systems in Bevy, depending on your needs. Although both options are possible, using a plugin is generally preferred for better replaceability and organization. The scaffolding process involves creating Component, Event, and System placeholders. It's important to note that the Components and Events should initially be empty structs. During this phase, focus on establishing a logical layout and a good naming for the new code.
  2. Review the scaffolded code, preferably with the assistance of reviewers or colleagues. Evaluate the logical flow and understandability of the plugin layout. Check if any crucial components are missing or if improvements can be made. This step ensures that the initial structure of your code is well-designed and easy to comprehend.
  3. Design the data for your plugin. Fill out the previously empty event and component structs, and consider creating additional helper structs if necessary. This phase is not about coding yet; rather, it lays the foundation for the coding phase and ensures that you have the necessary data structures in place. By carefully designing the data, you reduce the need for creating new data structs on the fly during implementation.
  4. Review the data design step again, if possible. Address similar questions as in the previous review, ensuring that the designed data structures align with the requirements and improve the overall design of the code. This iterative review process helps catch any potential issues or oversights before moving forward.
  5. Implement the systems by coding the actual functionality based on the scaffolded plugin or systems. This is the time to bring your ideas to life and write the necessary code to achieve the intended behavior. Take into account the previous steps, such as the logical layout and designed data structures, to guide your implementation. Write clean and readable code that aligns with best practices.
  6. Review the implementation and iterate based on feedback. Conduct a thorough review of the implemented code, either through self-review or by involving peers or colleagues. Carefully examine the code for any potential issues, performance bottlenecks, or areas that can be optimized. Take into consideration any feedback or suggestions provided and make necessary adjustments to improve the code quality. This iterative process ensures that your code evolves and improves with each review cycle.