JavaRush /Java Blog /Random EN /Coffee break #54. Anti-patterns to avoid in code. How to ...

Coffee break #54. Anti-patterns to avoid in code. How to learn how to solve problems in a technical interview

Published in the Random EN group

Antipatterns to avoid in code

Source: Free Code Camp Every developer strives to write structured, well-planned code with good comments. There are many design patterns with clear rules to follow and structure to keep in mind. However, we can still find anti-patterns in software. They are especially common in programs written long ago or in a hurry. A harmless basic trick added to solve a problem quickly can set a precedent in your codebase. Over time, it can be copied to several different places, which will turn this trick into an anti-pattern that you have to deal with.

What is an antipattern?

In software, an anti-pattern (anti-pattern) is a term for techniques that should NOT be applied when solving problems. Antipatterns are considered bad software design. They are inefficient and confuse the program. As a rule, this is code that needs to be returned to later and redone, that is, in fact, this is a technical debt. Coffee break #54.  Anti-patterns to avoid in code.  How to learn how to solve problems in a technical interview - 1There are six anti-patterns: Spaghetti Code, Golden Hammer, Boat Anchor, Dead Code, Code Growth, and Divine Object.

spaghetti code

Spaghetti code is the most famous anti-pattern. This is code with almost zero structure. It does not modulate anything. The files are scattered randomly in random directories. The course of the program is difficult to follow, it is completely intertwined like spaghetti. This problem usually occurs when someone didn't think through their program in advance and just started writing code right away. Coffee break #54.  Anti-patterns to avoid in code.  How to learn how to solve problems in a technical interview - 1Spaghetti Code is not only a maintenance nightmare. It also practically does not allow you to add new functionality. You will always break something. When you make changes, you can never be sure which parts of the codebase will be affected by the change. Because of this, you won't be able to accurately predict runtimes, because it's impossible to predict countless problems in such code. You can read more about spaghetti codehere .

golden hammer

Imagine this scenario: your development team is very knowledgeable about the new Hammer architecture. She was fantastic for all your past tasks. You are the best Hammer architecture team in the world. But now, for some reason, all tasks always end up using this architecture. Flat head screw? Hammer. Phillips screw? Hammer. What? Do you need a hex key? No, just hit with a hammer! So you begin to apply a familiar and beloved architectural approach everywhere. Yes, it is not the best solution for all cases, but it copes with the task! Although using a hammer will take you twice as long to write code, and the program will eventually become less productive, but for you personally, a hammer is convenient, because it is easier to take it. The problem here is that the golden hammer may not always be a universal solution. Different languages ​​have both common approaches to solving problems and their own standards. And if you have successfully applied something while working with one language, this does not mean that everything will turn out just as well in working with another. Don't neglect constant learning throughout your career. Choose the most appropriate language for each project. Think architecture and go beyond the ordinary. Explore and try new tools and new ways to solve problems. You can read about the golden hammer Don't neglect constant learning throughout your career. Choose the most appropriate language for each project. Think architecture and go beyond the ordinary. Explore and try new tools and new ways to solve problems. You can read about the golden hammer Don't neglect constant learning throughout your career. Choose the most appropriate language for each project. Think architecture and go beyond the ordinary. Explore and try new tools and new ways to solve problems. You can read about the golden hammerhere .

boat anchor

The boat anchor anti-pattern suggests that programmers leave unused code in the database because they might need it later. For example, the developers have written something slightly out of specification, and this code is not needed yet, but they are sure that they will need it next month. Therefore, developers do not remove this code. The code is sent to production so that later, when it is needed, it can be quickly used. But in the end, the codebase gets overwhelmed with redundant code, and maintaining this base becomes a real problem. Imagine that you urgently need to make some changes. You are desperately trying to figure out exactly which part of the code is responsible for sending customer card data to the API for withdrawing funds from the bank. In such a situation, you can easily waste time reading and correcting extra code without realizing that that you are not even in the right place in the codebase. Redundant or obsolete code increases build time, and you can mix up working and non-working code by inadvertently adding the latter to production. Now you probably understand why this anti-pattern is called a boat anchor: it's hard to carry (it increases technical debt) and it doesn't do anything (the code is completely useless, it doesn't work). You can read about the “boat anchor” antipatternhere .

Dead code

Have you ever seen code written by someone who no longer works for your company? For example, there is a function that seems to do nothing. But it is called from everywhere! You ask everyone about this feature, but no one knows what it does and therefore they are afraid to remove it. Sometimes you can see what a piece of code is doing, but you don't know the context. Basically, you can read and understand this code, but you don't understand why it's there. Such code is usually called dead. The most common occurrence of this anti-pattern is in code that was written for proof-of-concept and then put into production. This code is harmful because it cannot be determined whether it is needed for the program to work or not. Once, at one of the meetups, I met a guy who had just such a problem. His project had tons of apparently dead code and a lot of possibly dead code, but the management didn't allow all the dead code to be removed. This guy called his approach "monkey testing". With the help of comments, he started to turn everything off one by one to see what would break in production. Yes, it was a little risky! If you don't want to use monkey testing in your work, try to convince management that technical debt is a risk and that's why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead code but the manual did not allow removing all dead code. This guy called his approach "monkey testing". With the help of comments, he started to turn everything off one by one to see what would break in production. Yes, it was a little risky! If you don't want to use monkey testing in your work, try to convince management that technical debt is a risk and that's why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead code but the manual did not allow removing all dead code. This guy called his approach "monkey testing". With the help of comments, he started to turn off everything one by one to see what would break in production. Yes, it was a little risky! If you don't want to use monkey testing in your work, try to convince management that technical debt is a risk and that's why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead code With the help of comments, he started to turn everything off one by one to see what would break in production. Yes, it was a little risky! If you don't want to use monkey testing in your work, try to convince management that technical debt is a risk and that's why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead code With the help of comments, he started to turn off everything one by one to see what would break in production. Yes, it was a little risky! If you don't want to use monkey testing in your work, try to convince management that technical debt is a risk and that's why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead code try to convince management that technical debt is a risk and that is why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead code try to convince management that technical debt is a risk and that is why it needs to be cleaned up. Alternatively, write down everything that the module (section) you want to rewrite does, and start removing dead code bit by bit, using an iterative approach. At each iteration, check to see if anything has broken. This way you will understand which part of the code is important, and then remove the non-working parts. You can read about dead codehere .

Code Growth

Objects or modules regularly interact with each other. If you have a clean modular codebase, you will often need to call individual modules and new functions. The code-growth anti-pattern suggests that there are objects in the codebase that exist solely to call other, more important objects. They can be called "intermediary objects". The presence of such objects adds an unnecessary level of abstraction and only confuses when you need to understand how the program works. The best solution is to simply remove the extra object. Move the responsibility for calling the required object to the caller. You can read about code growth here .

divine object

If your codebase always requires access to one object, then that object may very well be "divine". Divine objects do too much. For example, they can be simultaneously responsible for the user ID, transaction ID, first and last name of the customer, the total amount of the transaction, the goods that the user buys ... In short, you get the idea. This anti-pattern is sometimes called a "Swiss knife" because you only really need it to cut off a piece of string, but it also includes a nail file, a saw, a pair of tweezers, scissors, a bottle opener, and a corkscrew. If you have such a divine object, it is better to separate it into separate modules. In object-oriented languages, the problem of divine objects is given special attention. To prevent their occurrence, you need to follow the principles of SOLID, which help us better model the software. The S in SOLID stands for Single Responsibility - each class or module is responsible for one part of the system, not several. You can see the "divine object" problem in the following example:
interface Animal {
        numOfLegs: string;
        weight: number;
        engine: string;
        model: string;
        sound: string;
        claws: boolean;
        wingspan: string;
        customerId: string;
}
Can you quickly look at this code and determine that the area of ​​responsibility here is too wide and refactoring is required? Here we are clearly witnessing the creation of a potential divine object. How about such a change?
interface Animal {
        numOfLegs: string;
        weight: number;
        sound: string;
        claws: boolean;
}

interface Car {
        engine: string;
        model: string;
}

interface Bird {
        wingspan: string;
}

interface Transaction {
        customerId: string;
}
Separation of interfaces will allow the developer to clearly see the area of ​​responsibility of each of them. Also, classes that only need wingspan won't need to implement engine, customerId, and model as well. You can read about divine objects here .

Conclusion

In any large codebase, there should always be a balance between managing technical debt, developing new features, and fixing bugs. I hope this article has helped novice developers understand what anti-patterns can lead to, and also taught some ways to fix such errors.

How to learn how to solve problems in a technical interview

Source: Codeburst “You have coins of different denominations. You also know the total amount of money. Write a program to calculate the smallest number of coins needed to add up to this amount." What code should be written to solve this problem ? Where would you even start? Google, Amazon, and all the big software companies almost always use something like this when hiring new employees. Don't be afraid if you don't know the answer. I still don't know him, as do 63% of all programmers who took on this task. What you really need to be a developer is the foundation, the principle of solving such problems, as well as the skills that will allow you to solve the problem that you will be offered at a technical interview. Coffee break #54.  Anti-patterns to avoid in code.  How to learn how to solve problems in a technical interview - 3Six months ago, I landed my first job as a full-stack web developer at a Fortune 500 company. In preparing for interviews, I encountered many of these types of tasks and spent countless hours solving them. In this article, I have tried to lay out five recommendations based on personal experience. I hope they will help you to be more successful in solving programming problems at a technical interview.

1. Use a timer or stopwatch

Think about how much time you want to set aside for yourself to complete one task, and stick to that plan. You may solve the problem faster, or you may not solve it at all - in any case, it does not matter . Once the time is up, stop working on the problem you were solving and move on to the next one. I'm serious. Your goal is to get a green checkmark or a gold star. Leave that pass/fail bullshit for elementary school , where it belongs. Instead, your goal should be to gain knowledge. How are they purchased? Through failure and adaptation. Again and again. To do this, you need to get acquainted with many different tasks. And quickly. When I started solving programming problems, I spent from 45 minutes to an hour on each and “failed” almost everything. Now I spend no more than 20 minutes on each problem and solve 50–75%, depending on the complexity. But forget about me: think of your own timer and set it however you like. Over time, you will find that you start solving tasks a few minutes faster than planned.

2. Set daily goals

This will help you focus and get rid of some distractions. Of course, it sounds simple, because everyone is capable of setting a goal. It is much more difficult to achieve your goals day after day. It's important to stay consistent here. One daily goal that you achieve every day is much better than five goals on Monday and none on Tuesday. “Compound interest is the eighth wonder of the world. Those who understand them earn money, and those who do not understand them pay,” Albert Einstein. In this quote, Einstein was referring to the well-known rule: "money makes money." If you eventually apply the same idea to your growth in knowledge, you will simply be unstoppable. There is one more thing that you might find useful. I noticed that I was great at following other people's instructions and terrible at following my own. Luckily, I found a way around this. If you have the same problem, write down your goals for tomorrow in the evening. Put them on the table and forget about them. In the morning you will wake up with a clear head, get up and notice a list of tasks on the table from a very smart and organized stranger. Another helpful tip: set a small number of easily achievable goals for yourself . Motivation is the key to success, and you're much more likely to hit 3 if you were aiming for 2 than if you were aiming for 30.

3. Stick to a certain system

When I solved daily programming tasks, I wrote notes for each one. The next time I look for a job, my goal will be to fill out another notebook . I am sharing this with you for two reasons. Firstly, because in my courses I learned a very simple note-taking system called "UPER":
  • U nderstand (understand)
  • Plan (plan)
  • E xecute (execute)
  • Review (check)
The first two steps must be completed before you write any code. To achieve anything, you must plan how you will do it. But before that, you need to make sure that you understand what they want from you. For example, what type of input will your function receive? What will be the output - a string or maybe a floating point number? Are you missing important information? Complete each step of your plan by defining variables and writing your functions. Then, finally, check the result: what you did well, what could be improved and what you were not sure about. I truly believe that programming challenges are one of the best ways to improve your skills. Yes, they are time consuming and you don't have to be so obsessed with solving them, but these daily exercises will take you to the next level.. You will learn a lot about your programming language and build up your analytical muscles. And when it comes time to write code at work every day, these muscles will come in very handy .

4. Get regular rest

Doctors confirm that our brains are more creative when we take frequent breaks. Fresh air and exercise are good for more than just health. When you're stuck on solving a problem, shifting your focus to something new can be the best way to move forward. A sudden flash of creative insight can come from anywhere. Especially often such outbreaks happen when you went outside to get some fresh air.

5. Learn from others

When mastering new skills in a field of activity unfamiliar to you, the greatest difficulty lies in the fact that you do not know a lot of things . It is difficult to determine this on your own, because without knowing the context, you simply cannot guess where to start. You don't know what's important and what's not. Functional programming concepts? Data structures? When I solve problems, I always look at other people's solutions, even if I solved the problem myself correctly. And be sure to take notes. Just because you've solved a problem doesn't mean you've exhausted your opportunity to get better. After all, there may well be a more elegant way of solving the same problem. For example, with fewer lines of code. Perhaps you could write a more efficient algorithm. Reading other people's decisions fits into the "verification" of the UPER system. Pay attention to how other people write code, and you'll be surprised how much you learn about your work.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION