DEV Community

Cover image for Why clean code matters
andersnicolai
andersnicolai

Posted on

Why clean code matters

In various consultancy projects, I have noticed lately that the same thing keeps repeating itself: clustered code. What do I mean by that? Well, let me put it this way. When you code, you should think about clean code. Yes, I know, one more person out there talking about clean code. Why should you listen to me? Since I was 12 years old, I was interested in computers and how things work. When I became 15 years old, I started watching Pluralsight, a bunch of videos on how to do MVVM, MVC, architecture, etc. I watched tons of videos, but I did not know how to program yet. I followed along, but I remember not understanding a lot of what was going on.

In the past years, I've been working as an architect and senior software developer for various companies. My background is in computer engineering and IT apprenticeship. And I try to share with you what I know, as you all know, to help people, but also to get exposure like all the people out there on LinkedIn. Yeah, they don't love writing as much as you think; it's purely a business model. But that doesn't matter, right? So here it goes. Hopefully, one day you'll buy one of my products. ;)

Now, let me tell you what I have seen lately in different projects. I think that the reason clean code isn't always applied isn't necessarily because people don't have the knowledge. It's often about strict deadlines and pressure from different projects. If you're a software engineer like me or a project manager, you know there are certain constraints and time pressures needed for a project to be successful.

In order to deliver to the client, and even when working in-house, you face deadlines and different stakeholders. Companies often operate on a subscription model where clients expect new features regularly. This creates a lot of challenges. Developers and project planners need to keep the project moving forward without falling into the trap of architectural debt because they didn't have enough time to think through the solution properly.

Once that problem is there, it’s really hard to go back and fix it. From my experience, people don’t often go back to refactor their projects—at least not the people I know. Let me know if you’re different. There are various things you can do to refactor, and it helps a lot, but the problem is that it’s not prioritized. If the code is working and the client is happy, refactoring isn't on the top of the list. But let’s think two or three years ahead. What will happen once the code becomes more and more clustered?

You might end up hiring a lot of developers to overhaul the monolithic architecture into a microservices architecture, which costs a lot of money. This is why you should think about clean code—not just when you start a project, not just when you wake up, but all the time. Because eventually, it will come back to bite you if you don't apply it.

Practical Strategies for Clean Code

Consistent Code Reviews
Regular code reviews ensure adherence to coding standards and catch potential issues early.

Automated Testing
Implementing automated testing, including unit tests, integration tests, and end-to-end tests, helps identify problems before they make it into production.

Refactoring Regularly
Set aside time in your project schedule specifically for refactoring to prevent technical debt from accumulating and to keep your codebase maintainable.

Adopting SOLID Principles
The SOLID principles (Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion) provide a framework for writing clean and maintainable code.

Clear Documentation
Writing clear and concise documentation helps new developers understand the codebase more quickly and reduces the likelihood of introducing errors.

Pair Programming
Pair programming allows two developers to work together on the same code, catching mistakes early and sharing knowledge among team members.

Long-Term Benefits of Clean Code

Reduced Maintenance Costs
Clean code is easier to maintain, reducing time and money spent on fixing bugs and implementing new features.

Enhanced Readability and Understandability
A clean codebase is easier to read and understand, crucial for onboarding new developers and for long-term project sustainability.

Improved Performance
Well-structured code leads to better performance by avoiding unnecessary complexity and optimizing resource usage.

Greater Scalability
Clean code allows for easier scaling of applications, simplifying the process of adding new features and adapting to changing requirements.

Increased Developer Satisfaction
Working with clean code reduces frustration and increases job satisfaction for developers, leading to higher productivity and lower turnover rates.

Example of Messy Code

<?php

class User extends security\Session
{
  protected $app;

  public function __construct($app)
  {
    $this->app = $app;
  }

  public function addSkill(Application $app, Request $request)
  {
    $userInput['id'] = $request->request->get('id', null);
    $userInput['id'] = preg_replace("/[^0-9,.]/", "", $userInput['id']);

    $app['checkpoint']->minimumRole(1);
    $user = $app['session']->get('user', []);
    $userId = $user['profile']['easyJobAddressId'];

    if ($userInput['id'] === null) {
      return $app->json(['ok' => true]);
    }

    $app['dbs']['appMySql']->insert('skills', [
      'skillId' => $userInput['id'],
      'userId' => $userId,
      'rank' => 0
    ]);

    return $app->json(['ok' => true]);
  }
}
Enter fullscreen mode Exit fullscreen mode

Refactored Code

The refactored code adheres to clean code principles by breaking down responsibilities, using dependency injection, and following SOLID principles.

Dependency Injection and Constructor

public function __construct(
    UserRoleService $userRoleService, RequestStack $requestStack,
    UserRepository $userRepository,
    EasyJobServiceInterface $easyJobService,
    SkillsRepository $skillsRepository,
    AppDataService $appDataService
) {
    $this->userRoleService = $userRoleService;
    $this->requestStack = $requestStack;
    $this->userRepository = $userRepository;
    $this->easyJobService = $easyJobService;
    $this->skillsRepository = $skillsRepository;
    $this->appDataService = $appDataService;
}
Enter fullscreen mode Exit fullscreen mode

By injecting dependencies, we ensure that each class has a single responsibility and can be easily tested and maintained.

Single Responsibility for Adding Skills

#[Route('/profile/experience/add', name: 'profile_experience_add', methods: ['POST'])]
public function addExperience(Request $request): JsonResponse
{
    $this->denyAccessUnlessGranted('ROLE_USER');
    $skillId = $request->request->get('id');

    if (!is_numeric($skillId)) {
        return $this->json(['status' => 'error', 'message' => 'Invalid skill ID']);
    }

    $userId = $this->getUser()->getId();
    $result = $this->appDataService->addSkillToUser($userId, (int) $skillId);

    return $this->json(['status' => 'ok', 'added' => $result]);
}
Enter fullscreen mode Exit fullscreen mode

Here, we use a dedicated method to handle the addition of skills. It ensures validation and follows a clean, concise structure.

Separation of Concerns

public function index(): Response {
    $user = $this->getUser();
    $userId = $user->getId();

    $allSkills = [90, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31];
    $skills = array_fill_keys($allSkills, 0);

    $userSkills = $this->appDataService->getSkillsByUserId($userId);
    foreach ($userSkills as $skill) {
        $skillId = $skill->getSkillId();
        if (array_key_exists($skillId, $skills)) {
            $skills[$skillId] = 1;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Notice how we use appDataService to decouple the system.
By separating concerns, we keep each method focused on a single task, making the code easier to read and maintain.

Conclusion

In conclusion, always think about clean code. It might not seem urgent now, but neglecting it can lead to significant problems down the line. Prioritizing clean code will save time, money, and headaches in the future. Refactoring regularly and adhering to coding standards are key to maintaining a healthy codebase. Remember, the effort you put into writing clean code today will pay off in the long run, making your projects more scalable, maintainable, and enjoyable to work on.

Top comments (0)