Mauro Morales

software developer

Category: Thoughts and Opinions

  • My Personal Experience Using AI

    There’s been a gigantic buzz around AI for a while now. Unless you’re living under a rock, it’s hard not to get hit by this topic. So, a month or two back, I decided to finally give it an honest shot and see if AI can bring any benefits to my work or personal life.

    Disclaimer: No AI assistant was used to write this blog post.

    Some colleagues have been using GitHub’s Copilot since the beta release and swear by it, and other colleagues say that OpenAI’s ChatGPT has become part of their daily flow, so I decided to try both.

    GitHub’s Copilot for code generation

    Context for AI is crucial, this is because AI models are trained based on datasets. The quantity and quality of such data, plus the given training algorithms, will result in the quality of the model, and different models will be better at different tasks. GitHub’s Copilot is designed to generate code, and it was trained with code they host on GitHub.

    At the time of testing Copilot, my main project is Kairos, an OS (and more) for Edge Kubernetes. Kairos specific software is written in Go, but like any other Linux distribution it’s full of configuration files, scripts and build tooling. Some of them are Dockerfiles to build images, configuration files for different utilities (e.g., GRUB), an Earthfile for building everything together, tons of YAML files and different shell scripts to do stuff here and there.

    I use IntelliJ’s Goland IDE, where you can effortlessly install and configure the Copilot plugin. However, the quality of the suggestions was terrible. Usually, there were no suggestions at all. It’s been only a couple of times when I was impressed with the generated code, but for my particular use case, I wouldn’t consider it worth the 10USD/month or 100USD/year price tag.

    To be honest, I was very disappointed. The experience is not at all what I was told, but there are many variables that could be causing this gap. For once, those who recommended it, all use VSCode as their main editor, and since it’s the editor GitHub uses in their workspaces it wouldn’t be a surprise that it is much better supported. Second, the type of project and combination of languages is different, but I would expect Go to be quite well-supported. I also don’t really know how well has been Copilot trained to make recommendations on how to configure GRUB, for example.

    But don’t let my words steer you away from trying it. See for yourself how well it works with your stack and setup, and then decide if the subscription is worth it for you. As for me, I will give it a shot using VSCode and if I don’t see a major improvement, then I will cancel.

    ChatGPT as a review partner

    I’m well aware that ChatGPT can be used for code generation, but I decided to only use it for other work related tasks. Like, for example, asking it to help me understand code, help me debug issues, or help me with technical writing.

    Case 1: Explaining code

    Digging through some code, I came across the following. Most of it was clear to me but, I didn’t understand the need for doing the last line.

    Prompt

    Can you explain the following Go code?

    type ImageExtractor interface {
    	ExtractImage(imageRef, destination, platformRef string, local bool) error
    }
    
    type OCIImageExtractor struct{}
    
    var _ ImageExtractor = OCIImageExtractor{}

    Response

    This Go code defines an interface called ImageExtractor, which has one method called ExtractImage. The method takes four arguments: imageRef (a string representing the reference to an image), destination (a string representing the destination path for the extracted image), platformRef (a string representing the reference to the platform the image is built for), and local (a boolean indicating whether the image should be extracted from a local or remote source). The method returns an error if any error occurs during the extraction process.

    The code also defines a struct called OCIImageExtractor. This struct does not have any fields or methods of its own.

    Finally, the code creates a variable of type ImageExtractor that is initialized with an instance of the OCIImageExtractor struct. This line of code uses the blank identifier (_) to indicate that we don’t actually need to reference this variable, we just want to ensure that OCIImageExtractor implements the ImageExtractor interface. This is a way of enforcing that any other implementation of ImageExtractor will also have a ExtractImage method with the same signature.

    I find this super useful. It feels like reaching to the dev at the desk next to me and asking them: “hey do you know what does this line here does?”. You cannot do this with search engines and have much success.

    Case 2: Explaining other technical topics

    Now it’s time to reach to the other side of my desk to that fantastic sysadmin.

    Prompt

    Why do I have some files called dm-0, dm-1, dm-2 under the /dev directory?

    Response

    The files you are referring to, dm-0, dm-1, dm-2, are device mapper (DM) devices. Device mapper is a Linux kernel framework that provides a generic way to create virtual block devices by mapping physical block devices onto them. It is commonly used to create logical volumes for managing storage in Linux.

    When you create a logical volume using LVM (Logical Volume Manager), the LVM creates a device mapper device file that represents the logical volume. The dm-X device files are the device mapper devices that represent the logical volumes.

    For example, if you create a logical volume named “my_lv” using LVM, a device mapper device file named “/dev/dm-0” will be created, which represents the “my_lv” logical volume. If you create another logical volume named “your_lv”, a device mapper device file named “/dev/dm-1” will be created to represent the “your_lv” logical volume, and so on.

    You can use these device mapper devices just like any other block devices, such as hard disk partitions or USB drives, to store and retrieve data. However, it’s important to note that the underlying physical devices that the logical volumes are mapped onto may change, so it’s important to use the logical volume names (e.g. “my_lv” or “your_lv”) rather than the device mapper device names (e.g. “/dev/dm-0” or “/dev/dm-1”) when referencing the logical volumes in commands or scripts.

    Thanks to this, I was able to sort out a problem I was having building some Kairos images and all I had was a hunch that it was related to those files.

    Case 3: Writing a call for paper for a conference

    During a pairing session with a colleague, we decided to use ChatGPT to help us write a call for paper for a conference. I will not post the prompt or result here, but it suffices to say that we were able to use about 50% of the generated text. While 50% might not be such a great result for a 3-5 paragraph text, it made the task less exhausting. Specially as a non-native English speaker, I find it useful to have some sample text and base my work from that.

    All in all, I would highly recommend that you start integrating ChatGPT in your daily use, specially if you are not working in a team that values pair programming. It has saved me a lot of time and mental effort. The answers are not always correct, but they constantly point me in the right direction. I’m currently not paying for the subscription, but it’s on my to-do list, so I can report later on if it’s worth it.

    Final Thoughts

    Just like with the introduction of search engines, I think we are at a similar inflection point. I’m not going to try to guess what AI will look like in the future, but from where I stand, I’m pretty sure AI will be a part of our everyday. For this reason, I think we really need to pay attention to it as individuals but also as a society. We must learn how to use it so that it can make our lives easier, that’s the whole point about technology, but we must understand that AI assistant are not encyclopedias, each tool has its purpose, advantages, and disadvantages. Talking about disadvantages, I don’t think we need to be afraid of it becoming conscious. But I do feel afraid of companies or governments abusing it, so we need to build these services with privacy for the individual and transparency. One of those solutions is the open-source project LocalAI, which I will share about in a next post.

  • The Maintenance Price Tag

    When adding new features to a software product, we tend to plan them by the value they bring versus the cost of development. However, it’s critical to consider that they also come with a maintenance price tag attached to them. Ignoring this cost, can affect the user experience, cause a system crash and/or make it harder to do any changes in the codebase.

    In an ideal world. We’d pay for the cost of developing a feature, but once it’s out, we’d never have to spend more resources on it. And while there might be a few software products out there, that run with minimal maintenance, we should not assume this will be our lucky fate. Yet, product and development teams alike, seem to think this is the case.

    Because of this misconception of pay once, enjoy forever, we constantly fail to evaluate the costs of maintenance of a product before we even start coding it and only address them when something is broken. We are even willing to cut corners deliberately to ship sooner because we believe that first to market wins the race every single time. And everyone starts noticing the problems:

    • Customers, experience a slow and buggy product.
    • Developers, have a hard time understanding and changing code.
    • Product, has to cut down features or cancel their development because the velocity of the team is too bad.

    Instead of addressing the problems, more corners are cut, and eventually, it becomes a habit and the only way you do things. By the time you realize, you have dug your own grave and, soon enough, start talking about full-refactorings. Paying some tech-debt is hardly ever an option. Developers are blamed for building such monstrosity, but product and business were right there at the co-pilot seat too.

    To avoid this situation, product and developers must work together to make maintenance part of the development process. The product team should, at the very least, have healthy buffers during units of work, so developers can address maintenance, but ideally understand it well enough, so they can be the ones planning for it. And the development team shouldn’t work without thinking of the maintenance impact of their code, and own their solutions all the way to production.

    The most important thing to understand is that, doing maintenance proactively, is always cheaper than having to react. And while fully getting rid of emergencies is not possible, reducing the amount of them will give you more time for feature work and will keep the stress levels of the team under control.

  • 10 Years Working Abroad

    Today, I’m celebrating 10 years since I moved to Europe and became a migrant worker. Living abroad helped me grow as a programmer, professional and a human being. This is a short summary about the process, challenges, and key learnings from this experience.

    In 2011, I finished my first big web development project, and it left me with the feeling that there had to be better ways to build software. This is how I found out about the Ruby on Rails web framework and its community. They were talking about practices like automated testing, which for me was something new and appealing. There weren’t many local or remote Ruby jobs I could apply, so I decided to search abroad.

    I reviewed hundreds of job openings (even those that were not sponsoring visas) to learn about the most requested skills and studied them. I also did a couple of pet projects and one freelancing gig. After many months of preparation, I felt confident enough, and started applying.

    As a university dropout, I was afraid no company would sponsor me. Thankfully, I already had six years of experience, so I was able to apply for a skilled-worker visa. With a university degree, this would have been a tad simpler because I’d have been able to request a blue card. In practice, however, I haven’t really noticed the difference besides the length of the validity of the permits.

    Challenges

    While living in Europe, I’ve had one or two really challenging situations. Like the time a company decided to cancel my contract only 2 days after we signed it. But these kinds of issues put you on fight or flight mode, and you find a way to overcome them. Yes, it was stressful, but I managed to find something new in less than a month. In my experience, the things which are more likely to break you, are the daily challenges like:

    • Long distance relationships: My wife and I have lived a third of these years apart. It’s important to be aligned and have a vision because there will be times when you need a reminder to not lose faith.
    • Lacking a support circle: I saw a major difference between the time I lived in Switzerland alone, and the years when my wife has been there to go through this adventure together. We’ve also made meaningful friendships along the way. These people don’t only make it easier to be abroad, they become so close that you build some of your most significant memories together.
    • Cultural differences: Sometimes locals don’t understand you, and vice versa. I learned not to take any of these differences personal. It’s possible to immerse in a different culture, without having to die in the process or lose your own culture.
    • General knowledge: There’s a lot of general knowledge you lack when you’re in new territory. The housing market, taxes and medical system can be tricky to understand at best. Simple things like the business opening hours can be frustrating. Thankfully, there’s a lot of information online, so it’s just a matter of investigating and learning to survive a few embarrassing moments.
    • The feeling of not settling anywhere: The excitement of a new place eventually fades away, and sometimes you can feel anxious about not settling. I’ve seen an improvement since I stopped overthinking about the next stop in our journey and focused on enjoying the current stop.

    Learnings

    Even with all those challenges, the experience of working abroad is very rewarding. Living in Central Europe, you can travel to many countries nearby, learn or practice one or multiple languages, attend many cultural and technological events, and much more. And while Europe might not be the tech mecca that developers see in the US, it is a great place to learn about software development.

    In Switzerland, my boss taught me a lot about Lean principles and system administration. I also learned about configuration management and hardening Apple’s OS. I wasn’t using Ruby on Rails that much, which enabled me to focus on learning Ruby and OOP.

    At SUSE, I learned a big deal about Linux and tooling. This was my first experience with Extreme Programming, and I saw my technical and soft skills grow exponentially. I learned to think more like an engineer than a developer. I also expanded my horizons and played a bit with new technologies, like the Go programming language and Docker.

    I then had two shorter but valuable experiences. One at Babbel, where I learned about Serverless on AWS, and another one at CloudBees, where I deep dived on the topic of CI/CD while working on CodeShip and Jenkins-X.

    To finalize this 10 year journey, I’m now learning how to lead a dev team at Ring Twice. I’m also figuring out how to work together with management to do company-wide changes to improve the development process.

    What’s next?

    The last decade has been a fantastic experience. I’m more than satisfied with how things ended up and would recommend anyone interested in working abroad to give it a try. For those interested but not able to move, don’t despair. The world is a very different place, and it’s a lot easier to find good remote jobs. If you have questions on how to get started, don’t hesitate to get in touch (social links at the bottom of the page).

    Whether we continue on our expat journey or not, it will depend on the professional opportunities that open up. While this uncertainty can trigger my anxious side, I’ve also learned to accept that much of the success we’ve had, was was just us riding a wave, and not the result of compulsory planning. Amor fati.

    In terms of career, my goal is to keep growing as a software developer and to become a better leader and mentor. I’ll also make a conscious effort to create my first information product. Stay tuned!

  • Using a Hackathon to Stress Test Your Development Process

    A hackathon’s value proposition is generally one of innovation. Companies see these events as an investment to come up with new products. However, I recently found out they are also a great way to teach us about existing flaws in our software development processes.

    I’ve participated in a handful of coding events before and have come to appreciate hackathons, as a good way to boost camaraderie and do some individual learning. That’s why I got very excited when a few months ago our CTO announced we were going to do ListMinut’s first hackathon. And so, for 3 days in mid-September, our product development team moved to the Belgian coast to design and code an MVP.

    Let me first give you a bit of context. ListMinut is growing, and while this is good, it’s also challenging. Just like most other businesses, at first, it was possible to add features fast and easy, but with time the development process became harder and slower and throwing more man-power doesn’t seem to balance the situation. This scenario is very similar to a city whose streets grew organically and were not designed with growth in mind. At some point, the excess in population causes the entire traffic system to collapse. Fortunately for us, software is way more malleable than a city.

    To mitigate these growing pains, there are two major changes we are introducing. On the operational side, we are setting agile processes in place to help us work smarter. And on the technical side, we are improving code quality and optimizing performance, while also evaluating architectural changes which can deliver long-term benefits. This is basically why I joined the team.

    The main motivation behind the hackathon was to address the latter. What I didn’t expect, was how good the hackathon would be, as a way to surface out any flaws in the way we work. You’ll see, as part of my work during my first four months, I’ve been pushing for (1) shorter-lived feature branches, (2) code reviews, (3) automated testing, and (4) improved code quality. The team has been taking all these changes very positively. I’ll even allow myself to say that they’ve even been somewhat enthusiastic about it, which not only has made my job much easier but is enabling us to rip off the benefits early on.

    During the hackathon, without any request from my side, the back-end team didn’t rush in to code like crazy but instead followed each of these 4 principles, which completely made my day. The fact that we did so, allows us to easily incorporate what we built during these 3 days without having to go through a big refactoring or suffering some high maintenance costs later on. This is already a considerable win, but I know we can still improve and the fast-paced rhythm of the hackathon was a great way to put our processes to the test.

    For us, it pointed out little communication problems which forced us to do some re-writes and some problems with WIP (work in progress) and bad design which gave us some ugly merge conflicts. These difficulties aren’t new to development teams, as a matter of fact, they are very common but sometimes challenging to see in the busyness of the day to day. So teams adapt and cope with them or worse yet, they start to think of them as myths. The good news is that our industry has been solving these issues for a while now, so we will follow some Lean/Agile advice while also improving our OOP design and iterate until this machine is finely tuned.

    I’m quite excited to be working as a part of a team that experiments and isn’t afraid of exposing its issues. I think this is the only way to learn and improve. If you’d also like to expose any issues with your development process, let me recommend that you do a hackathon and follow your existing development process, you might surprise yourself about what you find.