What I learned from my bitter experience (over 30 years in software development)

Original author: Julio Biason
  • Transfer
  • Tutorial
image

This is a cynical, clinical collection of what I learned over 30 years in software development. I repeat, some things are very cynical, and the rest is the result of long observations at different places of work.

Software development


Specifications first, then code


If you don’t know what exactly you are trying to solve, then you don’t know what code to write.
First, describe how your application works before you begin programming.

“Without requirements or a project, programming is the art of adding bugs to an empty text file” - Louis Sraigley

Sometimes even a “brief presentation” is enough - no more than two paragraphs describing what your application does.

There have been times when, due to unwritten steps, I spent more time looking at the code and wondering what to do next. This is a good sign that it is time to stop and discuss the situation with colleagues. Or maybe rethink the decision.

Describe the steps as comments


If you don’t know how to start, describe the top-level data flow in your application, simply in your native language. And then fill in the void code between the comments.

Or even better: read each comment as a function, and then write a function that does just that.

Gherkin helps you realize expectations


Gherkin is a test description format whose principle reads: “Given that the system is in a certain state, if something happens, then this is expected.” If you don’t use testing tools that understand Gherkin, it will give you a good idea of ​​what to expect from the application.

Unit tests are good, integration tests are even better


At my current job, we are testing only modules and classes. For example, we write tests only for the presentation level, then we write tests only for the controller level, and so on. This helps us understand whether everything is in order, but does not allow us to see the whole picture of what is happening - for this, integration tests that check the behavior of the entire system are much more useful.

Tests Improve APIs


We program within the framework of levels: there is a storage level that should make our data eternal; there is a processing level that must somehow transform the stored data; there is a presentation layer that contains information about the presentation of data, etc.

As I said, integration tests are better, but testing the levels themselves allows you to better understand how their APIs look. Then you’ll better understand the situation with the calls of something: is the API too complicated? Do I need to keep so much data nearby to make one call?

Do tests that you can run from the command line


I mean, not the command lines themselves are important for any object, but your knowledge of the commands for running the tests, your ability to automate their execution, which you can then apply in the continuous integration tool.

Be ready to send your code to the basket


Many of those who start developing on the basis of testing (TDD) are annoyed when you tell them that you may need to rewrite a lot of their code, including what you yourself wrote.

TDD was invented for throwing code: the more you learn about a problem, the more you understand that what you write will not solve it in the long run.

Do not worry about this. Your code is not a wall: if you always have to throw it away, this is not a waste. Of course, you have lost time writing code, but now you better understand the problem.

A good language has integrated tests


I assure you: if the standard language library has a testing framework - albeit a minimal one - then in the related ecosystem the tests will be better than in a language that does not have such a framework, regardless of the merits of the external testing frameworks for this language.

Thinking about the future means wasting your energy


When developers try to solve a problem, sometimes they try to find a way that will solve all problems, including those that may arise in the future.

I'll tell you one thing: these future problems will never arise, and you will have to accompany a huge pile of code that will not be used in its entirety, or you will have to rewrite everything because of the thuy heap of unused code.

Solve the problem now. Then decide the following. Then the next one. Once you notice a pattern that arises on the basis of these decisions, and only then will you find your “universal solution”.

Documentation is a future love message for yourself


We all know what kind of hemorrhage it is to write damned documentation on functions, classes, and modules. But understanding the course of your thoughts when you wrote this or that function can save your ass in the future.

Function documentation is its contract


Since programming with writing documentation, you are actually creating a contract (possibly with himself): "I would argue that this function does this , and it's what she does."

If you later find that your code does not comply with the documentation, then this will be a code problem, not a documentation.

If the description of the function has “and”, then this is bad


A function should do only one thing. When you write documentation to it and see that you have added an “and”, it means that the function does something else. Divide it into two functions and get rid of the “and”.

Do not use boolean values ​​as parameters


When developing a function, you might be tempted to add a flag. Do not do this.
Let me explain with an example: let's say you have a messaging system, and there is a function getUserMessagesthat returns all messages to the user. But there is a situation in which you need to return either a brief summary of each message (for example, the first paragraph), or the entire message. Therefore, you add a parameter in the form of a flag or a Boolean value that you name retrieveFullMessage.

Again, do not do this.

Because those who read your code will see getUserMessage(userId, true)and wonder what it is all about?

Or you can rename the function getUserMessageSummariesand enter getUserMessagesFull, or something similar, but each function will simply call the original getUserMessagewith trueorfalse- but the interface outside of your class / module will be understandable.
But do not add flags or Boolean parameters to functions.

Beware of interface changes


In the previous paragraph, I mentioned the renaming of a function. If you control the source in which the function is used, then this is not a problem, it is only a matter of search and replacement. But if the function is provided by the library, then you do not need to change the name on your own whim. This will break many other applications that you do not control and upset many people.

You can create new functions and mark the current function as undesirable in a document or by means of code. And after a few releases you can finally kill her.

Ugly solution: create new functions, mark the current one as undesirable and add sleepfunctions to the beginning to force those using the old function to be updated.

Good languages ​​have built-in documentation


If the language uses its own way of documenting functions, classes, modules, and everything else, and even there is a simple documentation generator, then everything mentioned will be well documented (not great, but at least good).

And languages ​​that do not have built-in documentation are often poorly documented.

Language is more than just language


You write in a programming language and make things “work”. But there are far from only special words in it: the language has an assembly system, a dependency management system, tools for interacting tools, libraries and frameworks, there is a community, there is a way to interact with people.

Do not select languages ​​for ease of use. Remember that you can find the syntax simple, but by choosing this language, you also choose the way the creators of the language communicate with its community.

Sometimes it's better to let the application crash than to do nothing.


Although this sounds strange, it’s better not to add error handling than to catch them quietly and do nothing.

Java has a sadly common pattern:

try {
  something_that_can_raise_exception()
} catch (Exception ex) {
  System.out.println(ex);
}

Nothing is done with an exception here, only a message is displayed.

If you don’t know how to handle the error, let it happen, so at least you can find out when it happened.

If you know how to process, do it


In contrast to the previous paragraph: if you know when an exception, error or result pops up, and you know how to handle it, then do it. Show the error message, try to save the data somewhere, discard the data entered by the user for later use in the log - just process it .

Types talk about what data you have


Memory is just a sequence of bytes. Bytes are simply numbers from 0 to 255. What these numbers mean is described in the language type system.

For example, in C, the character type (char type) with a value of 65 will probably be the letter “A”, and an int with a value of 65 will be the number 65.

Remember this when working with your data.

When adding booleans, many forget to check the number of values True. Recently I came across this example JavaScript:

console.log(true+true === 2);
> true
console.log(true === 1);
> false

If your data has a schema, store it as a structure


If the data is simple, for example, only two fields, then you can store them in a list (or a tuple if your language allows). But if the data has a scheme - a fixed format - then always use some structure or class to store it.

Recognize and stay away from the cargo cult


The idea of ​​the "cargo cult" is that if someone did, then we can. Most often, the cargo cult is simply an “easy escape” from the problem: why should we think about how to properly store user data if X has already done this?

“If the Big Company stores data in this way, then we can.”

“If Big Company uses it, then that's good.”

"The right tool for the task" is a way to impose your opinion


The phrase “the right tool for the task” should mean that there is a right and wrong tool for something. For example, using a specific language or framework instead of the current language or framework.

But every time I hear this expression from someone, people push their favorite language / framework in this way, instead of, say, the correct language / framework.

The “right tool” is more obvious than you think


Perhaps now you are participating in a project in which you want to process some text. You might want to say, “Let's use Perl because everyone knows that Perl is very good at processing text.”

What you forget: your team specializes in C. Everyone knows C, not Perl.

Of course, if this is a small project "on the knee", then it is possible on Perl. And if the project is important for the company, it is better to write it in C.

PS: Your heroic project (more on this below) may fail because of this.

Do not fit into what's outside your project


Sometimes, instead of using appropriate extension tools, people start changing external libraries and frameworks. For example, make changes directly to WordPress or Django.

Thus, you can easily and very quickly make the project unsuitable for maintenance. As soon as the new version is released, you will have to synchronize the changes with the main project, and soon you will find that you can’t apply the changes anymore, and leave the old version of the external tool full of security holes.

Data streams beat patterns


It's my personal opinion. If you understand how data should go through your code, then it will be better for him than if you use a bunch of design patterns.

Design patterns are used to describe solutions, not to find them.


Again my personal opinion. According to my observations, most often design patterns are used to find a solution. And as a result, the solution — and sometimes the problem itself — is distorted to fit the pattern.

First, solve your problem. Find a good solution, and then search among the patterns to know what your solution is called.

I have seen this many times: we have a problem, the pattern is close to the correct solution, let's use the pattern, now we need to add a bunch of everything to the correct solution, so that it matches the pattern.

Learn the basics of functional programming


You do not need to delve deeply into the questions “what are monads” or “is it a functor”. But remember: you should not constantly change data; create new elements with new values ​​(consider data as immutable); as far as possible, do functions and classes that do not store internal states (pure functions and classes).

Cognitive effort is the enemy of readability.


Cognitive dissonance ” is a veiled expression “in order to understand this, I need to simultaneously remember two (or more) different things.” And the more indirect this information has, the more effort you need to spend on keeping it in your head.

For example, adding booleans to count values Trueis a mild version of cognitive dissonance. If you read the code and see a function sum()that, as you know, adds all the numbers in a list, then you expect to see a list of numbers; and I met people who use Boolean sum()to count values Truein the list, which is completely confusing.

Magic number seven plus or minus two


The " magic number " is an article in psychology that describes the number of elements that a person is able to simultaneously hold in short-term memory.

If you have a function that calls a function that calls a function that calls a function that calls a function that calls a function, then this is just hell for the reader of your code.

Just think about it: I will get the result of this function, pass it to the second function, get its result, pass the third one, etc.

Moreover, today psychologists are more often talking about the magic number FOUR, rather than seven.
Think in the category of “composition of functions” (for example, “I will call this function, then that, then there ...”), and not in the category of “call of functions” (for example, “this function will call that, it will call that. .. ").

The cuts are good, but only in the short term


Many languages, libraries, and frameworks offer shortcut methods to reduce the number of characters you type.

But later it comes back to you, and you will be forced to remove the abbreviations and write everything in its entirety.
So first find out what a particular abbreviation is doing before using it.
You don’t need to write the whole thing at first, and then change it to abbreviation: do what the abbreviations do for you, and at least you will understand what might go wrong, or how to replace something with an unabridged version.

Resist the temptation of "ease"


Of course, the IDE will help you with the automatic completion of a bunch of everything and make it easy to build a project, but do you even understand what is happening there?

Do you know how your build system works? If you have to run it without an IDE, can you do it?

Do you remember function names without automatic completion? Is it possible to break something or rename it so that it is easier to understand?

Take an interest in what's happening under the hood.

ALWAYS use time zones in dates


When working with dates, always add time zones. You will always have problems with time zones mismatch on computers and on servers, and you will lose a lot of time for debugging, trying to understand why the interface displays the wrong time.

ALWAYS use UTF-8


You will have the same problems with encodings as with dates. Therefore, always convert string values ​​to UTF-8, store them in databases in UTF-8, and return from your APIs to UTF-8.

You can convert to any other encoding, but UTF-8 defeated the encoding war, so the easiest way to stick to it.

Start stupid


One of the ways to get away from the IDE is to "start in a stupid way": just take the compiler, ANY editor with code highlighting and - program, build, run.

Yes, it is not easy. But when later you use some kind of IDE, you will only think of the buttons “Yes, it launches that.” This is exactly what IDEs do.

Logs are for events, not for the user interface.


For a long time I used logs to show users what is happening with the application. Well, you know, because it is much easier to use one thing than two.

To inform users about events, use the standard output form. For error reporting, standard error messages. And use the logs only to store data that you can easily process later.

Logs are not a user interface, but an entity that you need to parse to retrieve information at the right time. Logs should not be human-readable.

Debuggers Overrated


I have heard complaints from many that code editors without debuggers are terrible, precisely because they have no debuggers.

But when your code is in operation, you cannot run your favorite debugger. Hell, you can't even run your favorite IDE. But journaling ... it works everywhere. You may not have the desired information at the time of the fall (for example, due to different levels of logging), but you can turn on logging to find out the reason later.

I’m silent about the fact that debuggers themselves are bad, they simply don’t provide the help that many expect from them.

Always use a versioning system


“This is just my stupid application with which I want to learn something” - this does not justify the lack of a versioning system.

If you use such a system from the very beginning, it will be easier to roll back when you make a mistake.

One change per commit


I met people who write the following messages in commits: “Fixes problem 1, 2 and 3”. Unless all these problems duplicate each other - of which two should already be closed - there should be three commits instead of one.

Adhere to the principle of "one change per commit." And by change I mean a change in one file. If you need to change three files, commit these files together. Ask yourself: “if I roll back this change, what should disappear?”

"Git add -p" will help you with a lot of changes


This applies only to Git. It allows you to partially merge files using the "-p" parameter, so that you can only select changes related to each other, leaving the others for the new commit.

Structure projects by data or type, not functionality


Most projects use the following structure:

.
+-- IncomingModels
|   +-- DataTypeInterface
|   +-- DataType1
|   +-- DataType2
|   +-- DataType3
+-- Filters
|   +-- FilterInterface
|   +-- FilterValidDataType2
+-- Processors
|   +-- ProcessorInterface
|   +-- ConvertDataType1ToDto1
|   +-- ConvertDataType2ToDto2
+-- OutgoingModels
    +-- DtoInterface
    +-- Dto1
    +-- Dto2

That is, the data is structured by functionality (all input models are in one directory or package, all filters are in another directory or package, etc.).

It works great. But when you structure according to data, it is much easier to divide the project into smaller ones, because at some point you may need to do almost everything the same as now, with only minor differences.

.
+-- Base
|   +-- IncomingModels
|   |   +-- DataTypeInterface
|   +-- Filters
|   |   +-- FilterInterface
|   +-- Processors
|   |   +-- ProcessorInterface
|   +-- OutgoingModels
|       +-- DtoInterface
+-- Data1
|   +-- IncomingModels
|   |   +-- DataType1
|   +-- Processors
|   |   +-- ConvertDataType1ToDto1
|   +-- OutgoingModels
|       +-- Dto1
...

Now you can make a module that works only with Data1, another module that works only with Data2, etc. And then you can separate them into isolated modules.

And when you need to create another project, also containing Data1 and working with Data3, you can reuse most of the code in the Data1 module.

Make libraries


I often saw how developers either create mega-repositories with different projects, or keep different branches, not so that they are a temporary environment for later joining the main part, but simply for splitting the project into smaller parts (talking about splitting into modules, imagine that instead of building a new project that reuses the Data1 type, I use a branch with a completely different main function and the Data3 type).

Why not allocate frequently used parts to libraries that can be connected in different projects?

The most common reason is that people don’t know how to create libraries, or are worried about how to “publish” these libraries to dependency sources without giving them away (so is it not better to understand how your project management tool gets dependencies so that you can create your own dependency repository?).

Learn to monitor


In a previous life, I added a lot of metrics to understand how the system behaves: how quickly it came, how quickly it went, how many things were between the input and the output, how many tasks were processed ...

This really gives a good idea of ​​the system’s behavior. Is speed decreasing? To understand, I can check what data comes into the system. Is speed reduction normal at some point?

The fact is that without further monitoring, it’s rather strange to try to find out how “healthy” the system is. A health check in the style of "Does it respond to inquiries" is no longer suitable.
Adding monitoring early will help you understand how the system behaves.

Use configuration files


Imagine: you wrote a function that you need to pass a value in order for it to start processing (say, the account ID on Twitter). But then you need to do this with two values, and you just call the function again with a different value.

It is better to use configuration files and just run the application twice, with two different configs.

Command line options look weird, but they are useful


If you transfer something to configuration files, you can make life easier for your users and add the ability to select and open the file.

Today, for every language, there are libraries that work with options for the command line. They will help you create a good utility by providing a standard user interface for everything.

Not just function compositions, but application compositions


Unix uses this concept: "applications that do one thing and do it well."

I said that you can use one application with two configuration files. And if you need results from both applications? Then you can write an application that reads the results of the second, and combines everything into a common result.

Even when using application composition, start stupid


The composition of applications can develop into microservices (which is good), but they require an understanding of how applications "communicate" with each other over the network (protocols and the like).
No need to start from this. Applications can write and read from files, so much easier. You will think about remote interaction later when you understand the network.

Leave optimizations for compilers


Let's say you need to improve performance. You may want to look in the code for “places where you can squeeze some more speed” or think “how to remove a few cycles here to make it work faster”.

Compilers already know how to do this. Smart compilers are even capable of deleting your code, because it will always generate the same result.

What you need to think about is a better project for your code, how to improve the current code. It is needed for people to read it. IS ALWAYS. And optimizations are done by compilers. So instead of using shorter words, find a more sensible way to explain in the code what you want to do.

Lazy computing


Once upon a time, in one small language, expressions were calculated not as they appeared, but as needed. This was the case in Lisp, and today many other languages ​​have come to this. For example, in Python there is an expression yieldthat stops the execution of the current function and immediately returns a value, picking up a new expression only after the function is called again. If you make a chain of functions that take results, then you do not need as much memory as functions that return lists.

In team and at work


The code review is not intended to test style


Take the time to review the code to identify problems in the architecture and design, and not in the style of code design. Nobody likes people who, after the audit, say “you have voids in this line,” “there is no space before the brackets,” etc.

And only if you find problems in the architecture or project, then you can also mention the design flaws.

There is nothing wrong with code formatting tools, but they are not a panacea


To avoid discussing style during code revisions, you can use the tools in the command to automatically format before sending commits.

Yes, this type solves the problem, but there is one “but”: we humans do not read code as easily as a computer. What is readable for a computer may not be suitable for us. Of course, language developers are trying to find a feed in which the code could be read by us easily, but it does not always work out well.

If you use the tool to format the code, use it to find the places where it changes the code the most. Perhaps these fragments are best simplified.

Follow Code Style


If your project has a specific style of code, you must abide by it. Sometimes this is not obvious (“should this class be singular or plural?”), But try your best to do it.

... if it's not Google style


Exclusively personal opinion, you can not agree. Every time Google crawls out with its code style, it starts to blaze. The community long before this corporation developed a more perfect style, and apparently, Google is trying to stand out with his style just to remind himself.

For C / C ++, there is only one code style - K&R


Again exclusively personal opinion. All other styles are MISTAKING :)

There is only one code style for Python - PEP8


Most of the community writes in PEP8 style. Observe it and your code will easily fit into your existing ecosystem.

Explicit is better than implicit


Do you know what is the worst name for a function? sleep().

How much do you need to fall asleep? Is it in seconds or milliseconds?

Explicitly state what you need. Options sleepForSecsand sleepForMsare not perfect, but it's better than sleep.

Keep this in mind when writing your command line interface or configuration file.

I can copy the entire Zen of Python book here, but try to focus on personal experience.

Companies are looking for specialists, but station wagons are held longer


If you know a lot about one language, this can make it easier for you to find a job. But in the long run, languages ​​will die, and you will need to learn something else. If you somehow understand many other languages, this will help you in the future, not to mention that it will be easier for you to find the best solutions.

“You should not learn a language that does not affect your understanding of programming” - Alan Perlis.

For a long time I kept to a simple rule: at home I write in one language, and at work - in another. This allowed me to learn new things, which I later applied in a working code base.

I found out how generics work in Java when I wrote code in Rust. I understood how dependency injection is done in Spring when I read about it in C ++.

Think about users


Think about how you will use the data received from users - today this is especially important, since “privacy” has become a luxury.

Having received the data, do not forget to protect it from intruders.

The safest way to work with user data is to not collect it


Do not hesitate, once the data is stolen, due to security holes or human intervention.

And if you do not collect user data - or keep it anonymous, then you will not have any problems.

Keep information about “stupid errors that took me more than an hour to fix”


Such errors include simple “forgot to add dependency” and “add clarification”. Although I tried, but I never managed to create such a list, mainly because I had to deal with stupid mistakes repeatedly, which took more than an hour to fix.

However, try to compile and replenish your list, because later you can check it and not spend so much time correcting it.

If this does not work on your computer, you have a problem


I saw many systems that would never work on an isolated computer, for example, development tools, because this requires a specialized environment.

And it really reduces productivity.

If your system will work in a specialized environment (and I include “clouds” in this concept), then consider how you can abstract everything that you use. For example, if you use AWS SQS (that is, a queue), look for a library that allows you to abstract the way the queue works so that you can start the system on your computer with RabbitMQ.

If you use something very specialized, you may need a self-written abstraction tool isolated from the main system so that you can safely develop your product.

Personal


When you need to stop, it's time to stop


Realize when you can no longer program. Be aware when you can no longer process information. Do not force yourself, otherwise it will be worse.

Once I tried to program during a migraine (not strong, but not weak). The next day, when I was better, I had to rewrite most of the code, because it turned out to be complete rubbish.

A code of conduct protects you, not them


If you are familiar with a language, library, or framework, find out the code of conduct adopted here. Instead of preventing you from giving your opinion, the code protects you from attacks because you cannot immediately understand what is happening here.

I say this because many complain about a code of conduct. But they forget that it is the code that allows you to join any project without fear of being called a "lousy salag" or sent to "read the docks before bothering us."

Also remember that many opponents of codes of conduct want to be able to hang labels on everyone.

Learn to refuse


Иногда нужно говорить «нет». Нет, я не могу этого сделать. Нет, это нельзя сделать в этот раз. Нет, я не думаю, что у меня получится. Нет, я не хочу это писать.

Однажды мне пришлось сказать нашему техническому директору: «Ладно, я сделаю, но хочу отметить, что не согласен с тем, что мы делаем». В результате приложение запретили именно за то, что мы делали.

Вы отвечаете за использование вашего кода.


Это трудно. Очень-очень трудно. В этом заключается разница между «свободой» и «ответственностью».

Нет ничего плохого в том, чтобы писать, к примеру, ПО для распознавания лиц и определения этнической принадлежности. Но вы помните о том, для чего это будет использовано.

Не говорите, что всё готово, если это не так


You are tired of doing the same thing over and over again. You remember that something strange may happen, but because of fatigue, tell everyone that everything is ready.

Do not do this.

Someone from the very beginning will test this strange scenario and immediately announce that the product is not working .

You will know yourself through bitter experience.


We are upset about code that does not compile. We are angry at customers whose desires are constantly changing.

And when this happens, we pounce on others. And you are having problems.

People feel displeased and annoyed by the code or architecture because they care


You will find yourself on the other side: you will describe some kind of solution, and in people it will cause discontent or annoyance. This is because they care about the product or code.

“Yeah, you do not like this criticized decision, because you care” - these were some of the best words that I heard in my address.

Learn from your troubles


You will feel discontent, frustration, frustration and anger. You yourself will create trouble for yourself. You will see others get into trouble over the same thing. Learn from it. Do not ignore.

I experienced from my own experience that when I am upset, I become aggressive. Now, when I notice that I'm upset, I ask someone for help. You feel relieved when you see that you are not the only one trying to solve your problem.

Pay attention to how people react to you.


I have the face of an "angry man."

Sometimes I ask something, and people backtrack slightly, as if I were telling them that their decision was wrong. Therefore, I have to add: "I do not want to say that this is wrong, I just wonder."

This can help protect you from troubles.

Learn to recognize toxic people and stay away from them


You will meet people who openly pour mud around everything, including others, even if they did not say a word to you. Stay away from these.

You have no idea how such an attitude will oppress you.

Beware of "micro-aggression"


"Micro-aggression" is an aggressive comment in small doses. For example, when someone calls you “this person”, or releases deceptively harmless comments about your position in any system.

It’s hard to fight, because they won’t listen to you when you say that they attack you. In addition, micro-aggression is difficult to recognize, because they are very small, but discontent will accumulate, and one day you will explode.

It is better to stay away from this and contact as little as possible.

No, I don’t think they can "fix"


Personal opinion. Someone will say: “Maybe if you talk to these people, they will stop doing this?”

I believe that they will not stop. For them, this has become a natural behavior, and most often they will tell you that you are mistaken (for example, because you do not understand that they are joking).

Toxic and microagressors can only be fixed if they are YOU


Until you realize that you are toxic or micro-aggressive towards someone, and you don’t realize that in this way you do more harm than help, the situation is unsolvable (this is again my opinion).

... mainly because hearing it from someone else, you can feel as if “they are against me!”

Heroic projects: one day you have to do this


I call “heroic” a project, a change in the specification or a framework that you personally think will solve a number of problems in your project. It could be a different architecture, a new framework, or even a new language.

That is, you will spend your free time writing what has already worked / existed to prove your point.

Sometimes this proves that you are mistaken.

But in any case, you will extract something for yourself.

Do not confuse “heroic project” with “hero syndrome”


I have met this at least twice: someone says that while he is not around, nothing works, or that he does not need help.

This is “hero’s syndrome” - a person believes that only he is able to solve all problems.

Don't be like that.

Be aware when you need to leave


You tell the boss that you did not finish on time, because something happened and he yelled at you.

Some of your colleagues are constantly attacking you.

Another all the time arranges moronic rallies, carries nonsense and flabbles with the participants of other teams.

The third always bays, that if he leaves, how everything ceases to work.

So, it's time to send out a resume, regardless of whether you are paid well and the project is cool.

... unless you want to turn into a constantly disgruntled and irritated type by forty.

IT world is very small


He really is very cramped.

The person with whom you work today will meet you again after 15 years, although both of you will already change 3-4 jobs.

And during this time you will meet many other IT people.

And they will talk about themselves.

And everything that you say or do will be discussed, someone will hear about it and tell in another company, from which others will pick up a rumor, another company will learn about it, and suddenly it turns out that no one wants to hire you in the city , because everyone knows about how you failed the project or gave a colleague in the face.

Paper notebooks are really useful.


I have tried many times to refuse to use paper. But in the end I confess that it’s really convenient to have a small notebook and pen on hand to write down the damn URL to which you want to send data.

Trello is cool and all that, sticky notes are better


Nothing illustrates the phrase "I'm really busy, but organized", like a bunch of glued leaflets on your desk.

It's better to talk about your stupid blog decisions than to be silent


It may seem to you that you "have done too little to talk about it," or "it’s such dumbness that it’s better not to talk about it."

Create a blog. Write about your moronic decisions. They are still better than anyone else.

Then return to this topic and showcase new, better solutions.

Show your height.

In addition, it helps you keep small notes or remember what needs to be done.

... just turn off the comments


Your stupid decisions will attract the attention of those who only want to mock you. For example, "it's stupid." Someone will say “you are an idiot”, not understanding who of you is really an idiot.

Turn off comments. Do not let others stop you.

Publish your stupid decisions online


No need to keep Github for “cool, almost perfect” projects. You can show that you were once a beginner.

You can always come back and improve the code.

Or you can not do this: I have a public repository with my first project in Python, which looks like I translated Java into Python, only without the Python part.

Make a list of “what I don’t know”


Richard Feynman, a renowned physicist, had a notepad entitled "What I Don't Know."

When you come across something interesting and you want to know more about it, create a file, create a notepad or something else with a similar heading. And then take notes on what you find or find out.

Also popular now: