Laravel & Unconventional Database – Why You Should Avoid That

Choosing the right database for IT projects is no easy task — it depends on business requirements, but also on limitations introduced by costs, legal issues, and even the ability to find the right technical support. In this blog post, based on our experiences at Ingenious.BUILD, I’d like to discuss the challenges of using an unconventional database like CockroachDB in a project based on Laravel, among other platforms. These challenges can also arise when our API uses completely different solutions.

Continue reading “Laravel & Unconventional Database – Why You Should Avoid That”

Why and how you should update your technology stack

Technology stack is often discussed during planning new projects or during recruitment process, but is often overlooked when it comes to dedicating time and resources to updates – and it is huge mistake, because the consequences can be really serious. I would like to present the reasons why it is worth taking care of the current technology stack in a company that creates and develops software. I would also like to show how the necessary changes can be put into practice. If I can convince even just one person – it will be a success and will contribute to better work of many people, as well as higher quality of the product.

Why technology stack updates are important

Security and clients security

The most important thing is security. Outdated technology stack means vulnerabilities – a lot of them. It is normal, software has gaps, security issues and other problems, nothing is perfect, and it is not possible to create complex applications without issues. But one thing is to know about that, and second to react properly: if we will just ignore this… we will pay a lot. Our clients will be also in danger, so it is crucial not to forget about security. One outdated library can be like an open gate in an ancient city: it does not matter how strong walls you have, because attackers can use just this one gate to break all security stuff.

Even if it is related to internal-only systems, outdated tech stack can be a problem – imagine situation, when someone tries to steal some info from company, or gap in main security features will allow to access internal systems. System or human fault, it does not matter, because the effect will be the same: a lot of issues, even including total destruction of the company due to loss of customer confidence. Would you trust the company yourself if you knew it didn’t care about updates and your valuable information was being processed by outdated systems?

Tech Debt

The tech stack a company uses can also have a significant impact on its technical debt. Technical debt refers to the cost of maintaining and updating older code and systems that are no longer optimal – and for developers, it can be a real nightmare. As technology advances, it’s common for companies to accumulate technical debt as they struggle to keep up with the latest trends and tools.

By upgrading their tech stack, companies can reduce technical debt and ensure that their systems remain up-to-date and efficient. For example, a company that switches to a new programming language or framework can often see significant improvements in their code quality and maintainability, which can reduce the need for ongoing maintenance and updates. Windows has millions of code lines in C, but last time Microsoft decided to move some critical part to Rust. Why? To avoid memory issues, they often cause security problems and controlling that aspect on C or C++ is much harder.

On the other hand, a company that sticks with an outdated tech stack can quickly find themselves buried in technical debt. As their systems become more difficult to maintain and update, their overall productivity can suffer, leading to longer development cycles and slower time-to-market. AGILE? Yes, it’s still possible, but much harder if you need to fight with tech debt.

“It’s not enough to be up to date, you have to be up to tomorrow.”

David Ben-Gurion

Performance & costs

Please do not forget about performance. Why is it important? Lower performance can be a problem on the client side, especially if we talk about classic desktop applications, but right now we have more and more services in the cloud. If we offer backend on our side, within our infrastructure level, every bottleneck will affect not only clients, but also our total costs. Outdated tech stack can require additional machines, additional traffic and of course, additional maintenance time. All of these items mean more money we will spend to make the service available.

Up to date tech stack can resolve many performance issues, because new versions usually provide fixes and improvements – usually, because sometimes updates generate regressions, also moving to additional abstractions layers will add some impact, but in long-term perspective, it will improve stability. If the company will require outsource maintenance of some service, it will be also easier and cheaper if it uses up to date tech stack. Working with old systems may be very difficult and good example is a process of removing Windows XP and then Windows 7 support: a lot of companies decided to use extended long term versions and continue that even EOF – in this situation, migration to new option can be even more expensive.

Easier to hire better employees

Technology is constantly evolving, and companies that fail to keep up with the latest advancements risk losing out on top talent in the recruitment process. Developers are naturally drawn to the latest and greatest tools and technologies, as they are often faster, more efficient, and more flexible than older ones. By upgrading their tech stack, companies can not only improve their overall productivity but also make themselves more attractive to potential hires.

In the highly competitive tech industry, developers are constantly on the lookout for new and exciting opportunities. By offering a cutting-edge tech stack, companies can stand out from their competitors and appeal to the best and brightest in the industry. This can be especially important when it comes to hiring top-tier developers who have their pick of job offers. By demonstrating a commitment to staying ahead of the curve, companies can position themselves as leaders in their field and attract the most talented candidates.

In addition to attracting top talent, upgrading your tech stack can also help to retain existing employees. Developers are more likely to stay with a company that uses modern, up-to-date tools and technologies, as they want to work with the latest and greatest resources available. By investing in tech stack, you can show your team that you value their skills and are committed to helping them succeed. This can lead to a more engaged and motivated workforce, which in turn can drive better results and improve your overall bottom line.

No zombie projects

The last but not the least. If company takes care about upgraded, there are no zombie projects on their flow. Zombie project is a type of project, when we planned something, added to our backlog, but there was always something more important… It is like a zombie: it is dead, but can always move, hit us and generate a lot of issues when we will not have any time to fix them. Outdated, but still working software is a natural candidate to be zombie. For developers, it can be difficult to argue that updates are necessary, especially if company is under pressure and must deliver a lot of new functional changes.

How to update the technology stack

Monitor upgrades & vulnerabilities

First step to handle outdated tech stack is to have proper knowledge about that – it is required to monitor used libraries, new versions and important upgrades. Some tools like npm, yarn or composer offers very easy way to get all info about possible upgrades. Maybe not all of them will be possible to do at the same time, the knowledge about gaps is the most important item.

Plan, allocate time

When you have information about all outdated solutions, there is a time to plan next actions: check dependencies, check what should be changed to make codebase compatible with new solutions, plan all tasks. An important step is to define clear deadlines for these tasks. If there is no such information, these upgrades will be transferred into zombie items and will make themselves known at the least expected moment as mentioned in paragraphs above.

Implement upgrades

Finally, it is time to transfer goals into reality. It may be time consuming, but remember, it is worth it. Make backups, if change can break important systems, make that in iterations i.e., replace old solutions step by step, use a lot of internal, and also A/B tests on the users’ side.

Repeat & automate

The most important thing: doing that once will not help us. It should be part of the standard process; company should have clear updates policy to be proactive and avoid issues on eleventh hour.

Few words about technical debt

If you work in IT, you probably have seen or heard the “technical debt” term. Do you know what it is? Just as the name suggests, it is a type of debt, and nobody likes to have debts, right? Similar to monetary debts, if we do not repay it, it will accumulate interest and make our work harder and harder. It may be complicated systems, lack of tests, non-documented code, tightly coupled components, complicated infrastructure or just lack of module ownership. Sounds familiar? Yes, it is a frequent problem in software development, but not only there.

Technical debt is often created when we have a fresh, great idea and want to expand quickly: there is no time for polishing, we want to cover as many needs as possible and find investors. It is fine, if we will focus on details, we can lose our chance or be overtaken by bolder competition. In effect, we often create something called “big ball of mud”: it will work, but it will hard to maintain, it will be something like mix of different solutions, lack of plans, lack of information. Such a mix based on the knowledge of team members and if they will leave, everything will be complicated for new employees.

Technical debt can destroy a company

A notable example of technical debt is Symbian, an old mobile operating system created by Nokia. I have used Symbian for a few years on different devices and it was fine, but I did know anything “under the hood”. The truth was a bit scary: the system was super complicated, the building process was awfully long, testing was almost impossible. In effect Nokia hit the wall and it was not able to extend or improve Symbian anymore. Next part of this story was sad: Nokia was acquired by Microsoft; they completely stopped all projects related to Symbian and moved to Windows Phone only. Unfortunately, Microsoft failed to properly advertise and develop Windows Phone and after just a few years, this project was canceled. Nokia was sold again and was almost non-existent for some time. Now it produces phones, but they are only a shadow of their former power.

We can find many similar examples, even companies like Facebook, Google, Amazon or Netflix had and still have a lot of issues related to technical debt: there were a lot of moments when these companies were close to “death” because of that. These companies were not able to deliver new functionalities, compete on the market and attract new customers. Why did they survive and Nokia not? Because the magnitude of the problem was realized in time and faced up to it, instead of sweeping the issue under the rug – it was always hard, but required time, something like a big house cleaning before Christmas. Probably nobody likes that, but can you imagine Christmas in a mess?

Is technical debt always bad?

Based on previous information, you can assume “yes”, but the answer is more complicated. technical debt is not bad, it is not good. It just exists because during our work, we have to deal with a lot of complicated problems and in many cases, do not have enough time to do this correctly. If we must compromise, we will generate new technical debt. In the ideal world, we can always make correct decisions, we always have time to handle items in proper way and do not generate any bottlenecks and issues. Unfortunately, we do not live in an ideal world: deadlines, customer requests, competition. All these factors cause us to take shortcuts, generate new debt, for example by extending old codebase instead of making refactor, by skipping important tests or critical validations on CI/CD pipelines.

But technical debt can be beneficial. If we will remember about its existence and periodically clean up the mess, we can also adopt (yes, like in AGILE), learn, and do not repeat similar mistakes in the future. Probably we will never completely avoid technical debt, but we can learn how to live next to it and keep growing. And it is completely fine. Also, remember, that “technical debt” does not mean only IT projects. We can use the same words to describe even our personal troubles, it works in the same way and… Maybe it is a good analogy to explain how important it is?

Brownfield and Greenfield in software development

Software development is a complex project, especially if we work with something more complicated than just a simple CRUD application. If we want to cover a lot of business needs, we will have more and more requirements, new dilemmas, new use-cases and also a lot of things to monitor and check. Today I want to write about two project types: Greenfield and Brownfield. The fun fact is that nomenclature is from architectural business… and I work with software for architectural business, with AECO (Architecture, Engineering, Construction and Operation). Want to check? Visit Ingenious.BUILD on LinkedIn, we are hiring now. 

Ok, so what are the differences between them? Brownfield investment is an approach when we want to build something using existing terrains, existing buildings. We will have some existing problems to resolve, contaminations to remove or we will be removed by some law requirements related to the area we are interested in. Just imagine old buildings, maybe something like an abandoned former factory, big terrain you want to change to a new residential area. The Greenfield project is on the other hand something fresh. You have clean terrain and you can start everything from scratch, without checking anything from the past, no top-down restrictions, no complicated law processes.

The thing is similar in software development and software architecture, but with some important differences. According to what I wrote before, you can think that the greenfield project is always a better opportunity, and always gives us a better start. It is not true in the software world. Brownfield is like work with existing legacy code – and who does really like legacy, especially complicated legacy solutions? In this situation we have to rethink a lot of already existing parts of the system, we have to refactor some of them or just put them into the trash and write something again. It may be boring and it may be confusing for a lot of developers. The thing changes when we are at the point of contact between our code and our business requirements. Why?

The answer is simple: a brownfield project means we already have a lot of information. Yep, maybe we will need to adjust something, maybe remove or add something, but we already have a starting point, we already meet some business requirements and we can use that knowledge to improve our application. Just imagine building something like an Uber system from scratch and with something existing: there is a very very small chance that legacy code is completely useless: you can use it to determine requirements, check them and adjust. It’s even possible you will still use some of the parts, because they are good enough and will not require immediate refactoring. Also, if we already have some legacy solutions, we can easily add new members to our team, because we know what stack we use. It may not be super important at the start, but if we want to scale up, it will be more and more crucial for faster onboarding and verifying. Product part of our organization also has less to do, because we can reuse existing solutions. 

On the greenfield project the situation is only seemingly simpler. Of course we can start from scratch, but in most cases, we will have many more questions than answers: what are our real requirements? What business problems do we want to solve? What stack should we use for that? If everything is clear, we have all the information, then yep, it will be a piece of cake. But it’s a utopian assumption: we will not have all the information and business will verify our plans after first usage. That is why quick implementation – even if our application is not perfect, not ready for all cases – is so important: we will have feedback and it will be possible to make all required adjustments. And guess what… your greenfield project becomes a brownfield project then – you will avoid it only in very simple cases. 

Architecture Decision Record (ADR)

During software developing we often have some questions, especially when we join existing projects: why app uses that language? Why these solutions? Why we handle time or money values in such way? All these questions are very important, because it is a part of application architecture. Of course we can on team knowledge, but such method is not efficient and not possible to maintain on larger projects and when we want to scale up: new people will join, but some people will also leave project. Important knowledge distributed partially to different people will be hard to get. The solution is ADR: Architecture Decision Record.

Architecture Decision Record is just a document with information about why and when team decided to use some solutions. It can describe additional context and consequences of adopting the decision. In effect, we have one, central place with all required knowledge, with history and detailed descriptions. It helps during onboarding new people, because they can check ADRs quickly. It helps if we lost some project members, because we will not lost important knowledge. It also helps if we make changes on some modules ownership, introduce internal structure changes, because we still everything important in one place. Finally, it allows us to such documents in code, explain why we make adjustments – everything is clear then.

When should we create ADR?

As soon as possible. It is long-term solution – we will not see positive effect immediately, but after some time, it will help us. More detailed question: should we create it only for bigger things, or also smaller? It is flexible. We definitely should describe bigger decisions, in smaller it depends how they will impact our application. We can start to write ADR when we have a problem, even if we do not have any solution for that problem: it allows us to aggregate potential options, then discuss and finally decide and approve the best approach. In such case, we will have clear history what prompted us to make this decision.

ADR example

There are many different patterns of creating ADR and there is no right answer for question “which one should I use”. It depends on your needs, application structure,

NUMBER – ADR NAME

Status

(…)

Date

(…)

Context

(…)

Decision

(…)

Consequences

(…)

And real example:

1. Use standard HTTP response codes

Status

Approved

Date

26/02/2022

Context

There are many possible options to send responses – even if action will fail (for example we cant find model), it is still possible to send completely different response code (example: 200 OK). We should avoid that and make all responses clear, predictable and easy to interpret: we can use our rules, or follow global HTTP recommendations.

Decision

We decided that we will always use only valid, recommended HTTP response codes, for example 403 if access is forbidden, 404 if we will not able to find model etc.

Consequences

– All new endpoints will return only valid codes

– We will not accept custom or invalid response codes on code reviews and merge requests

– Legacy endpoints will be updated during required refactors

Where should we store ADRs?

Similar to how should ADR look like, there is no simple answer, but there is the same rule: you should define one place and use it for all ADRs. You can store them on repository and make close to code, you can use shareable notes, cloud with just txt files or anything else. The important part here is: you should backup your ADRs (or service you will use should offer that) and also, it should be possible to share ADRs for read-only. It’s required if you want to link to them in code comments, tasks descriptions or other architecture considerations.