5 Programming Tips To Be A Better Developer

5 Programming Tips To Be A Better Developer

In my previous article, I wrote about 5 non-technical tips to be a better developer. This is the 2nd part of that article, where we will explore more technical aspects of becoming a great programmer.

This article is meant to be a bit broad to help find specific items a developer can focus their time on piece by piece.

1) Learn to Name Things

Naming things is an important aspect of programming, as it helps to make the code more readable and maintainable. To make things more complicated, there is no hard fast rule on how to name things. In face, I've written a separate blog entry dedicated just to naming things.

2) Incorporate a Linter / Code Cop

Using a linter or some sort of code cop might seem nit-picky and tedious at first, but it will help you become a better developer. It will help with naming things because they tend to force consistency. And they can help alert you to code smells or anti-patterns you didn't even know existed. And, many of them will tell you why it's an issue and how to fix it.

If you use a CI/CD pipeline and do PRs you can even incorporate these into your builds so that you enforce linting across the team. I've found there is ALWAYS push back against this, but the code quality always gets better.

3) Practice Single Responsibility Principle

If you've been digging into object oriented programming then you may have heard of SOLID. But for me, the most important part of SOLID is the S for Single Responsibility Principle or SRP for short. It works beyond just OOP in my opinion.

What is Single Responsibility Pattern (SRP)?

Robert C Martin describes SRP as

A class should have one, and only one, reason to change.

In other words, your classes should have a singular responsibility that they tackle. However, I would argue that your functions should also follow this principle to reduce cognitive complexity of your code and make it easier to read. I often find that if I need to write a comment explaining what a piece of code does, then I need to break it down into smaller functions.

public class PatientRegistration {
    constructor(private http: HttpClient) {}

    public function registerPatient(patient: Patient) {
        // check if the patient already exists in the system
        let existingPatient = this.http.get('/patients/' + patient.id);
        if (existingPateient == null) {
            // create the patient in our system
            existingPatient = this.http.post('/patients/', patient);
        } else {
            existingPatient = this.http.put('/patients/' + existingPatient.id, 
                existingPatient);
        }
        
        // assign the patient to a room
        const rooms = this.http.get('/rooms/');
        const room = rooms
            .filter(room => !room.isOccupied && room.isCleaned)
            .first();
        room.patient = existingPatient;
        this.http.put('/rooms/' + room.id, room);
        
        // email patient
        this.http.post('/email/patient-registration', patient);
    }
}

Go easy on my typescript psudo-code. But let's dig into this registerPatient function. It's technically handling 3 different responsibilities that should be moved into their own functions or into their own classes. I've taken a stab at cleaning this code up a bit below.

public class PatientRegistration {
    constructor(
        private patientApiService: PatientApiService,
        private patientRoomService: PatientRoomsService,
        private emailService: EmailService){}
        
    public function registerPatient(patient: Patient): void {
        let patientEntity = this.savePatient(patient);
        this.patientRoomService.addPatientToRoom(patientEntity);
        this.emailService.sendPatientRegistrationEmail(patientEntity);
    }
    
    private function savePatient(patient: Patient): Patient {
        let existingPatient = this.patientApiService.getPatient(patient.id);
        if (existingPateient == null) {
            // create the patient in our system
            existingPatient = this.patientApiService.saveNewPatient(patient);
        } else {
            existingPatient = this.patientApiService.updateNewPatient(patient);
        }
        
        return existingPatient;
    }
}

Notice how the registerPatient function is now much smaller and the function names act as comments to tell us what is happening. This reduces this class to be closer to SRP and reduces the cognitive complexity of the registerPatient function to something that is much easier to read.

4) Learn Common Programming Patterns

Learning different programming patterns is a great way to add additional tools to your tool belt. And like any good craftsman, you need to know the tools of your trade. The trick is knowing when to use them, and that just takes time.

There are several books on learning design patterns for programming, but the book my mentor gave me and I return to every now and then is Design Patterns by Gamma, Helm, Johnson, and Vlissides. It doesn't matter what language you code in, these patterns are pretty universal.

Avoid Anti-Patterns

While learning programming patterns is vital, I also believe learning anti-patterns is equally important. Learning what NOT to do is an important skill and just knowing about some basic anti-patterns can help you gain a much strong nose when it comes to code smells.

Also, many design patterns can easily fall into anti-patterns. The Singleton pattern can be found in the Design Patterns book I linked to above. However, Singletons can be considered an anti-pattern.

5) Learn Docker / Containers

There are countless reasons to learn docker for someone in Devops, but I'm just going to point out what I've found most useful.

  1. Using containers for local development allows you to create an environment that is MUCH closer to the environment that you will be running in production.
  2. You can specify versions of required software easily and upgrades are easy. An example is specifying a version of node for your application.
  3. New developers can install docker and get started almost instantly instead of having to install all the required software.
  4. Knowing some of the basic infrastructure that your software will be running on can help you to write code that scales better

That last point is maybe the best point. It's easy to write an app that mimics twitter. It's hard to write an app that scales like twitter.