Posts

Showing posts from 2024

Proprietary Systems and Distributed Monoliths

Image
Distributed Monoliths are the predominant form of modern legacy systems. Sometimes distributed monoliths are created by teams misapplying microservices architecture due to lack of isolation or internally shared libraries break of isolation. Other times, there is just the proverbial no time to refactor. Let's share the database. However, sometimes distributed monoliths happen due to non-obvious reasons from decisions that, at first glance, sound like good ideas and are even far away from engineering.  In software, we often run a trade-off analysis, Build vs Buy, where we must decide whether to build or buy software. Buying is usually attractive because it gives some speed (since you don't need to code it). Building, of course, takes longer, and you will need to maintain it; there is a chance of the project failing, and you invest money and have no software. There are trade-offs between building and buying. However, people often think buying has no implications and is much better...

Expectations

Image
Every single day, engineering teams need to do magic. Such magic manifests in several different shapes and forms. It could be by making hundreds of assumptions, figuring out what to do with little to zero context, and delivering decent solutions with proper architecture, design, comprehensive testing, and value via continuous delivery. It's a lot. In reality, most industries use Scrum/SAFE, which is far from the best way to work. In theory, when you are doing Scrum, if you do not finish a story during the spring, it's not a big deal; you go to the next one, shift the stories to the following spring, and it's all good. However, in reality, it is not exactly like that, unfortunately. That happens for various reasons: ignorance of what proper agile looks like, irrational pressure, industry pressure, and hundreds of other uncontrolled and hidden variables. Lean is all about learning to see waste, remove it, optimize it, and improve it with more quality. Companies, unfortunately...

Functional Programming

Image
There are many programming languages. Most of them are based on C. However, there are a few different schools of thought. There are imperative, object-oriented, and functional schools and a couple of branches and variations, but that's the mainstream of languages you will see in production in big companies. Programming languages is how we express our intents and turn that intent into value for people. Usually, people are concerned about how other engineers would read the code, make sense of it, and be able to effectively maintain it. System programming languages like C and Zig tend to focus more on performance over abstractions (which always have a cost). Object-oriented programming languages like Java focus more on structure and how to abstract things. Abstractions are not necessarily bad if done right. They have a cost and impact on the people who maintain them. Having more abstractions on the SDK or standard library is a good thing for mantainance and increases people's kno...

My third book is out: Continuous Modernization

Image
After 7+ months of hard work, my third book is out. Introducing:  Continuous Modernization : The never-ending discipline of improving microservices, monoliths, distributed monoliths, individuals, and teams at scale. Modernization is something I have done over and over in my life. Modernization is something that all companies need and will always need. The need for modernization will never go away, even with LLMs and AI. Technical debt, Anti-patterns, and bad decisions do not take days off. Complexity never shirks and continually grows. Companies do not stop getting bigger and doing more and more software critical to growth, delivering value to customers, and staying competitive and relevant in the market. We need a better way of doing software to drive the best outcomes out of us. Continuous modernization is the counterforce to technical debt and anti-patterns. Continuous modernization is how to continually improve, even when you think it's impossible and nothing can be done. We ca...

Proper Error Handling

Image
No matter what programming languages you use. Engineers need to make dozens to hundreds of small decisions every day. Such decisions can sometimes save us and, other times, create many problems. Some of these decisions can be called assumptions. Depending on the context, they could be the side-effect, lack of proper discovery, feature factory rushing to delivery, or lack of care. In reality, error handling is one of the most challenging things in computer science, alongside naming, cache invalidation, and off-by-one errors. We usually get error handling wrong. When we are supposed to throw an error/exception and crash the application, we are unlikely to return some bad, sneaky default that will produce a bug down the road; when we need to ignore missing information, we end up crashing the app. Code reviews rarely to never review error handling. It's common to see services in production that don't even have the proper exception track due to improper error logging. Error handling...

Legacy Systems and Distributed Monoliths

Image
We can't have all the software in one system, even if we try. By nature, distribution will always happen. Decades ago, SOA set the standard for creating proper services that prime interoperability. Distribution is not bad; it's how systems work at scale. When companies buy products, they add more distribution because there is no system in a complete vacuum. Now, when we have distribution instead of modules in a monolith, we need to have a way for the system to communicate. When we have a proprietary system, communication options can often be pretty limited. Ideally, communication is thought ahead of time in an approach we call contract first. Where we define contracts and explicitly manage contracts aiming for interoperability. Usually done via a common interoperable interface like HTTP or, nowadays HTTP/2 or even HTTP/3. Legacy systems usually are not API friendly and, therefore, limit your ways of comunication. Such limitations can be drastic to the point where you might only...

The Dark Side of LLMs

Image
AI is the most considerable hype right now.  It is not as new as people think, starting in the 1950s. Significant advances have happened since 2017 with the  transformers architecture , which is the heart of all generative AI. There is an excellent potential for substantial disruption  because of AI. We are seeing significant improvements, but we are far from AGI. AI can be practical and honest, add value to the business, and improve our lives. AI is narrow at the moment and has many challenges. One of the industries that has the potential to be highly disrupted by AI is the technology industries and engineers.  Large Language Models (LLM) can do amazing things. From generating text, generating creative images and videos(with lots of problems), and even generating code. It's absolutely normal to be concerned, but the more you understand what's actually going on, the less you need to be worried. If you are an expert, you will be fine. We saw a great leap and boost of...

Testing Queues and Batch Jobs

Image
Testing could be considered a solved problem. Everybody knows the importance of testing. Unit testing and integration testing are not rocket science. However, it is still not uncommon to see a lack of testing, poor coverage, and flaky tests in the industry. Internal service implementation can be tested using fakes and mocks. Testing classes is a simple task if you have a good design. Refactoring a legacy system to have a better design makes it easier to test and could be more entangled, but it is still possible and desired. However, sometimes you have a good design, which is still hard to test. Some architectures can be more complex to test naturally. If we consider standard RPC services, it's pretty vanilla to test them. However, things get more messy when we consider integration tests or end-to-end testing, mainly because of dependencies and state. From the test point of view, RPC services are simple. You have a request, very likely a rest call, and you have some assumptions; you...

Frontend / Backend Distributed Monolith

Image
The current trend in front-end development is to be full stack. Being full-stack, has advantages from an efficiency point of view. However, having people proficient in both the front and backend can be challenging. The trend is that many javascript frameworks, initially only client-side, are moving to the backend and becoming full-stack frameworks. Backend change is happening gradually, probably starting with server-side rendering ( SSR ). Now, it is possible to have react code in the backend, which is referred to as react server components ( RSC ). Such an approach is not new. PHP , Rails , and Django have been doing that for decades now. Within similar timing, we saw the rise of HTMX where the backend levering HATEOAS returns HTML rather than just returning JSON. Interesting times. React is not the only framework (because it's not a lib) doing such a thing; we also have  Next.JS (on top of React), Svelte , Nuxt  and here is a good article on server components if you wan...

Service Chain

Image
Services are a very important architectural construct. Proper services( POSAM definition and principles) are even more important. However, not all services are the same. Not all APIs are the same, and definitely not all services are the same. Just having a Service or API, we can call it many different ways; the question is how good it is and how solid it is. I still put my money where my mouth is and say that services are a very powerful concept and the right level of abstraction for most problems. However, when a service is presented to you, you cannot assume you will have high quality just because it's a service. IF services are desired, multiple services must still be desired; after all, service orientation is about having services, not libraries. However, we know that when the granularity is wrong, and when we move data and capability to the wrong places, let's say, the wrong domain, we make things worse, not only risking breaking isolation but also leading to wrong abstra...

Tech Debt First

Image
Everybody is familiar with the concept of technical debt. Some people might refer to it using different metaphors, Fowler calls it cruft , Allan Kelly call it a liability . I personally prefer Kelly's definition. No matter what metaphor we use, technical debt is a reality in all industries. Technical debt is everywhere.  Not all technical debt is created equal. Some problems are worse than others; for instance, if we have 6 lines of duplicate ifs inside a single method or function, it's not as bad as a distributed monolith. Have you ever tought about what's the norm? Do you think technical debt is the exception, the anomaly? Or do you think technical debt is the norm and happens by default? We will go back to this question later. I believe it's impossible to avoid technical debt. IF you think about it, let's say you have the perfect team and the talent. It's amazing; all your team members have 20+ of experience, in the same industry and have been working togeth...

Ignoring Culture

Image
IF you did not watch the Netflix show: Downfall the case against boing . Please drop everything, go watch it, then come back to my blog post. You really need to watch it. I've been following the 737-MAX drama closely since 2019. Now if you watch the Netflix show and read this link . You will see why I'm doing this blog post. Because I believe there are valuable lessons we can learn from software engineering. Let's first review the technology industry's state of affairs: Waterfall projects are everywhere, thanks to SAFE. Technical debt is never so high, and the tendency is to get even worse over time. LLMs are great but also a great way to add more technical debt faster into the systems. Now, if you think this is a rant, you are wrong. IF you think I'm overstating that SAFE is evil, go read this about what the Agile co-creators said about SAFE .

Blameless Feature Reviews

Image
Have you ever wondered if what you build has the right impact on the customers? Engineering is often demanded to be on time and cost-effective.  Bugs and incidents are known for disrupting the customer experience. Less bugs, the better; fewer incidents, the better. So when do we reduce bugs and incidents? Devops has an interesting practice called Blameless Incident Reviews  (BIR). Considering the devops culture and movement, blameless incident reviews are great because they drive the right culture shift from feat and blame to sharing and understanding. BIR is often pull-based, which happens when we have a number of production bugs that are worth sharing and driving lessons learned to the whole org. Devops is all about better ways of building and operating software. We cannot do better if we are stuck with the same practices all the time; practices need to be changing and evolving and a way to keep us fresh and learning at all times.

The Cost of Silence

Image
All engineers and professionals in the tech industry, at least one time or multiple times in professional life, suffered from impostor syndrome. Besides the impostor syndrome, as humans, we dont like to receive bad feedback. Remote work can often be a source of more silence than would usually happen in a face-to-face work environment. Everyboddy is on the call with the video off, just audio, why would you turn your video on? You are joining a new team, you don't ask questions, you wait for the last minute when you need to code something, then you "might" ask questions. It's possible you are wondering now: What do impostor syndrome, zoom calls, onboarding new team members, and asking questions have to do with such a blog post? Is it all ramblings? No. All these moments build up on something I'm calling: The Cost of The Silence. Silence is not desired; meetings that are supposed to reduce the cost of silence, like Daily meetings, fail the goal and often just bring w...

Refactoring: Making sense of the invisible

Image
Refactoring is so underrated and misunderstood. There will never be enough books or enough blog posts about it. It's something that we need to keep revisiting from time to time. Very few people deeply understand it, but one thing is for sure: genuine and spread across the whole industry like wildfire: fear of refactoring. Fear can be a powerful feeling and an excellent way to keep you in check with reality, especially in difficult economic times. Still, fear can also be a significant source of blindness, inertia, and illusion, leading to bad economic decisions. Refactoring is not a binary decision; you either do it all and re-write the system or do zero-to-nothing. Companies and engineers need to apply more refactoring daily , and this matter is definitely unbalanced. Software at scale makes complete rewrites almost impossible. No company can stop the business for years and still succeed; many companies have tried and failed financially and in rewriting. So don't do more refact...