homepublicmail
{{platform}}
jam-platform.devsymbiotejs.org
mail[email protected]send@rnd_pro_chat
RND-PRO.com

The path of Full Stack

I often hear the opinion that there are no real Full Stack developers. It is believed that those who call themselves such often have a strong bias towards one area of knowledge, and have only superficial knowledge of others. And most of the time, that's true. Knowing everything is physically impossible, and the more you know yourself, the more obvious this simple truth becomes. In development, it's not just about knowledge itself, but also about more subtle matters, like engineering intuition, which is formed only with experience. And gaining full-fledged experience in tasks of different classes simultaneously is practically impossible. Being a Full Stack developer is definitely fashionable and prestigious, but does this title inherently come with the impostor syndrome?

Let's break it down.

First, let's clarify the general understanding of the term "Full Stack". To avoid misunderstandings, in this specific article, I would narrow the scope of this term to the field of web development.

So, a Full Stack developer is someone who:

  • Is able to fully solve tasks for both the server and client sides of a web application (this is the foundation, it's clear)
  • Has a good understanding of efficient data storage and mechanisms for exchanging data between different parts of the system
  • Has a good understanding of the capabilities and limitations of each subsystem
  • Has an understanding of the risks and threats to data, as well as ways to counter these threats
  • Can identify the "bottleneck" in the overall system performance and determine a strategy for dealing with loads, transferring them from the server to the client or vice versa
  • Understands the general principles of effective data visualization
  • Feels at home among browser APIs
  • Knows at least one tool from the entire frontend library zoo well
  • Understands how to test, monitor, and maintain all of this, at least at a basic level

It's clear that these points (except the first one) are conditional and variations are possible, but, in my opinion, it's already quite daunting. Additionally, one can add knowledge of the basics of UI/UX design, databases, and the ability to build communication within a team across a wide range of complex topics and work directions.

Now, a bit about the actual advantages of working with such specialists. Why do we need such a "Frankenstein-combine" in a hypothetical team, if we can hire simpler guys with a narrower specialization?

In my view, there are a number of obvious advantages and a couple of less obvious ones:

  • Holistic perception of the system, the ability to identify common priorities or problems for the entire system
  • A much less pronounced "welder's mask" effect - a state where the developer clearly understands the details and depth of a specific task but poorly understands what and why he is doing in general
  • Savings on communication - sometimes (and even often), it is significantly easier and faster to solve a task in all its aspects oneself than to coordinate such a complex solution with other developers
  • Savings on technologies - if some element of one part of the system can be reused, such a developer will know about it and will try not to create unnecessary entities
  • Savings on concepts and approaches - the same as with technologies, but more in the space of ideas, paradigms, and general engineering culture in the team
  • Good potential for leading a technical team - the ability to speak with everyone in a language they understand is invaluable for any leader
  • Ability to conduct experiments with controlled costs - quick and inexpensive testing of full-cycle hypotheses is the basis of commercial success for many projects
  • Ability to effectively solve R&D tasks - a general outlook and all other points help here
  • Well-suited for starting a new project: when you need to roll out an MVP quickly and then scale up production capacity later, analyzing feedback from the first users and the market reaction, without losing control over the technical implementation

Of course, nothing should be considered absolute, and I admit that in some cases, everything listed will have low or moderate importance. But there are also cases where this will be crucial for the success of the entire project.

To what end?

Everything you will read next is my personal opinion, I do not claim to be a Full Stack guru, and I base this on my own patchwork experience, which no one is obliged to replicate exactly.

My main message is this: you can become a fully-fledged Full Stack developer by reducing the number of entities you operate with when solving tasks, using universal approaches and modern web platform capabilities.

JavaScript - as the primary language

I can already see how many people are getting ready to throw a shoe. Wait. It is traditionally believed that JS is a bad language and almost the main hereditary trauma of the web. I used to think the same way. But about 10 years ago. Since then, much has changed: I have become more experienced and wiser, and JavaScript itself and its set of popular runtimes have become significantly more perfect. Now I consider JS a great language: powerful, expressive, performant, safe, and truly universal.

Modern tools like TypeScript allow for writing high-quality industrial code without compromising in complex cases. The main advantage of JS is the ability to write client and server code without any compromises, using common tools and project settings. This helps reduce overhead in working with the environment, which is quite significant.

Moreover, you can write code that will run in the browser and on the server at the same time. This is extremely useful for describing common data classes, common data processing functions, and in many other cases. You save a lot of time and resources on typing, documentation, testing, and maintaining code consistency. JavaScript is a silver bullet for Full Stack developers.

For those cases where JS is not suitable, for example, when the highest speed of calculations is needed or manual optimization of memory usage is required, you can use workers or bindings to components of the system written in other languages, for example, Rust. It's not very difficult to do this.

Use modern standards

This section complements the previous one. In JavaScript, native modules - ESM have been around for a very long time, and they are the standard. They are supported by all modern browsers and Node.js. They allow you to write, test, and debug isomorphic code without the need for additional configurations. They allow you to dynamically fetch dependencies via HTTPS requests and store parts of the application, for example, in a CDN, fetching what is needed at the right moment and providing additional optimization opportunities without unnecessary complexities.

TypeScript

Strive to describe types for all key modules in your system. Types, besides preventing errors, help you navigate the code better, which is especially important when mentally switching between client and server contexts.

Moreover, you don't even have to use TypeScript syntax: you can get all the benefits of static type analysis using declarations in JSDoc format and, optionally, additional descriptions in *.d.ts files. You will have access to generics, utilities, type inference during entity initialization - in general, everything that is indispensable for serious development.

But why would you ever need to write code NOT in TypeScript? It's very simple: you will be able to run and debug a snapshot of your entire project at any time, without any additional actions or configurations. The stack trace during debugging will fully correspond to your source code without the need to use Source Maps. You will be able to simplify writing tests by using absolutely any module of your code as an endpoint. You will be able to navigate to entity definitions in your code if parts of your code are connected as external dependencies. This is especially useful if you are a library developer. You will be able to reuse your code in other projects, regardless of whether they use TypeScript themselves. You will be able to verify the operability of your code before describing types well and in detail - this can speed up problem solving and reduce the cost of experimentation in R&D. Another plus is the ability to automatically generate documentation and a ready-made format for comments for this purpose - saving on approaches.

By the way, many people, when they hear about types in JSDocs, mistakenly oppose this method to TypeScript itself, which is certainly incorrect. Technically, you are using the same static analysis, but with a different format of declarations. Despite its orthodoxy, this approach is being used by an increasing number of developers, particularly those I would call experienced (judging by their publications on specialized resources). The main advantage of the approach lies in simplifying processes, which is exactly what will help free up additional resources to achieve "Full Stackness".

JAMStack

This is a slightly more complex section, despite the fact that JAMStack is conceptually quite simple. First, I would like to clarify what exactly is behind this trendy term for those who may have missed it. So, JAM stands for JavaScript + API + Markup. JAMStack is a set of architectural principles that allow you to achieve high performance, scalability, reliability, accessibility, and security of your web solution relatively easily, thanks to the fact that the main resources in it will be represented as a set of pre-generated static assets (in particular, HTML files), usually available via CDN. For the dynamic part of such an application, JavaScript is used, with which requests to the necessary APIs are made. At the same time, serverless functions (Serverless Functions or FaaS) can be used to work with APIs. Thus, the very concept of a server, in its more classical understanding, can be completely excluded from your system.

A small addition about APIs. Personally, I have encountered discrepancies in how the use of APIs relates to the JAMStack concept. Some believe that it provides interaction with the dynamic parts of applications, while others believe that APIs should be used at the static build stage (for example, when using Headless CMS). I suggest treating both of these options as equal in this context.

What does this approach give to a Full Stack developer? It reduces cognitive load and simplifies the set of measures to achieve what has already been mentioned above: speed, security, reliability.

Are there any downsides to this approach? Almost none, primarily because this approach does not limit you in applying any other approaches (if necessary), either in a hybrid form or in combination with them. However, in my opinion, it's easy to fall into the trap of excessive complexity in the asset generation stage, which can be observed in popular solutions like Next.js... But that's probably just my personal taste.

AI Assistants

While AI is not yet capable of fully replacing a developer in a team, it can become an invaluable assistant. Interestingly, the more experienced you are, the more valuable this assistance can be, because you are better at asking the right questions and you have the necessary level of general expertise to evaluate the correctness of the answers. AI is a great way to smooth out all the rough edges in your knowledge and get rid of the most glaring gaps. I would advise any developer, especially those aiming to achieve the coveted Full Stack zen, to practice working with AI assistants.

Conclusion

More than 15 years ago, I made my first Full Stack project. It was a simple website, almost entirely static, with only a couple of sections regularly updated: a schedule of concerts and a guestbook. It also included a forum on PHPBB. The main, in terms of volume, work was the creation of a flash game-presentation with 3D graphics, which caused some kind of wow effect at that time, but was quite primitive by today's standards. The server-side was written in PHP, also quite primitive, without any frameworks. The project was indeed not very technically complex, but the fact that I implemented it myself, alone, independently working on it in all aspects, from design with 3D graphics and all the code, to deploying LAMP, gave me a pleasant feeling of omnipotence. I realized that I could be my own team and take on projects, focusing on a more general vision, rather than being limited to details from just one area. On the other hand, I saw around me guys who had gone far ahead in their specialization, and I didn't want to feel inferior to them in any way. Since then, almost continuously, I have been searching for my path that would allow me to solve complex tasks and do it really efficiently.

Author: Alex Matiasevich [RND-PRO.com] © 2024
26.08.2024

AI as a Platform

New risk for our jobs or new opportunities?