DEV Community

Cover image for The One Thing Every Developer Should Know

The One Thing Every Developer Should Know

Brock Chestwall on December 18, 2023

Introduction Let's get to it: simplicity in coding. Imagine your code—clean, clear, easy to understand. That's simplicity. Whether you'r...
Collapse
 
jonrandy profile image
Jon Randy 🎖️

Sorry, but this is a pretty poor example. The 'unsimple' code is perfectly easy to follow, and the 'simple' code is major overkill for such a basic task, and following it requires opening 5 files.

Embracing this level of abstraction to make such a simple program is almost certainly the wrong thing to do IMO - and knowing this should be another thing that comes with experience.

Doing it might be a wise move if the 'task' formed part of a larger program where many of the component parts could be re-used nicely, but here it makes no sense at all. It's architecture for architecture's sake.

Collapse
 
jonrandy profile image
Jon Randy 🎖️

INot sure

Collapse
 
kingtouan1703 profile image
Dinh Anh Tuan

Agree!!!

Collapse
 
brock_chestwall profile image
Brock Chestwall

While I don't understand you argument, I hope we can learn to change your perspective on the issue. Sure, "abstraction" is the way to go, but shouldn't we opt for more general programs?

Collapse
 
dagnelies profile image
Arnaud Dagnelies • Edited

I had a good laugh. You transformed a few lines of simple code in a bunch of useless abstractions over several files. Congrats!

This could lead to a challenge of who writes the most contrived abstractions for the simplest tasks! Let's make a builder for the factory and throw a singleton in the mix! 😂

I seriously wonder if the post was a piece of sarcastic/ironic humor or not. 😅

Collapse
 
simongreennet profile image
Simon Green

The original code had five comments. The new code had none. That makes it instantly much harder for the next developer who looks at this code to figure out what is going on. You may know the five files are, the next person doesn't.

Collapse
 
brock_chestwall profile image
Brock Chestwall

You're right, I usually like to add an introduction to each file, but for the sake of brevity for the post– I omitted the comment headers here.

Here's how I would make the revised code structure clearer:

/*
  Purpose:
  This file defines a class named OutputFactory, responsible for creating an instance of an output service.

  Behavior:
  - The class contains a method createOutputService, which instantiates and returns a new ConsoleOutputService.
  - The ConsoleOutputService is assumed to be a service responsible for handling console output operations.

  Motivation:
  - The OutputFactory pattern is used to encapsulate the creation of output service instances, providing a centralized point for instantiation.
  - The use of a factory allows for flexibility in changing or extending the type of output service without modifying the client code directly.
  - This modular approach supports better code organization and maintainability by separating the concerns of output service creation from the rest of the application.

  Note: The actual behavior of ConsoleOutputService, as well as its dependencies, is not provided in this code snippet.
*/
const ConsoleOutputService = require('../services/ConsoleOutputService');

class OutputFactory {
  createOutputService() {
    return new ConsoleOutputService();
  }
}

module.exports = OutputFactory;
Enter fullscreen mode Exit fullscreen mode

Without context, the code will be hard to reason about indeed!

Collapse
 
brock_chestwall profile image
Brock Chestwall

Haha, I'm glad you liked the post!

I think "contrived abstractions" is a little harsh for the first example. There are actually more abstractions in the revised version– an "abstraction" is really what's missing to make this code scalable in a serverless context!

Collapse
 
joolsmcfly profile image
Julien Dephix

Not sure what to think of this post. If it were published on April 1st then I'd have hi fived you.

Now, let's assume you're serious and really thought this post through.

Comments in the "horrible" code are useless as they add no value so removing them would be my first "refactoring". I'd also inline filePath as it's only used once.

const fs = require('fs');

try {
  const fileContent = fs.readFileSync( 'example.txt', 'utf8');

  console.log('File Content:', fileContent);
} catch (error) {
  console.error('Error reading the file:', error.message);
}
Enter fullscreen mode Exit fullscreen mode

Next I'd look at all those, erm, ONE line of code and wonder:

do I need an abstraction layer for a self-explanatory method, namely fs.readFileSync?

Answer is no so I'd leave the code as is and move on to another task.

The original idea of your post is good: simplicity is key. Your implementation is far from being simple.

Don't use a tank to kill a fly.

Again, not sure if this is mocking people who overkill?

Collapse
 
brock_chestwall profile image
Brock Chestwall

IMHO, every code problem appears to be a "fly" until you need the "tank". Better be precautionary than regretful in the long run! But thank you for sharing this alternative angle, it helps to have a free discussion in these forums.

Collapse
 
joolsmcfly profile image
Julien Dephix

Sure, we should be cautious when writing code but you rarely find yourself in need of a tank overnight. When/if you do it's more often than not at the database level.

Now, back to your example (cos I really am not sure whether you're taking the piss or not), do you really think this code is, and I quote you, poorly organized?

const fs = require('fs');

try {
  const fileContent = fs.readFileSync( 'example.txt', 'utf8');

  console.log('File Content:', fileContent);
} catch (error) {
  console.error('Error reading the file:', error.message);
}
Enter fullscreen mode Exit fullscreen mode

Because translated to plain English it gives us:

grab a book
read it
Enter fullscreen mode Exit fullscreen mode

Your implementation:

see a book
ask neighbor for a book grabber
use book grabber to grab a book
ask neighbor for a book reader
use the book reader
Enter fullscreen mode Exit fullscreen mode
Collapse
 
bwca profile image
Volodymyr Yepishev • Edited

The true solution lacks Typescript, interfaces, abstract classes, method overrides, package.json and over 9000 gigs of node_modules :)

Collapse
 
kurealnum profile image
Oscar

Might be satire, I'm not sure. Either way, I just follow the rule of "abstract when you need to, don't abstract when you don't need to".

And this is definitely a case of "don't abstract when you don't need to"

Collapse
 
michalkuncio profile image
Michał Kuncio

Your example is basically what senior would not do, rather"clever" mid by creating tons of useless abstractions and regret it in a few months/years. And those factories... Why...

Collapse
 
tandrieu profile image
Thibaut Andrieu

There are still hard-coded values in your code (example.txt), and your module structure is tightly coupled with file system (../services/FileReaderService).

You should put an abstraction over this. Put your class in packages and use a "PackageDiscovery" pattern so that you would just have to write the package name. If it is not available locally, download it automatically using system's package manager. Any Senior developer know this !

Collapse
 
brock_chestwall profile image
Brock Chestwall

Ah, yes! At my business we call this the "Chance Pattern"– it's an effective means of adding more value to the existing codebase.

I'll consider your proposal with great haste– thank you!

Collapse
 
m0n0x41d profile image
Ivan Zakutnii

The one two things that every developer should know are type theory and how to code without states.

Image description

Collapse
 
brock_chestwall profile image
Brock Chestwall

Interesting... could you elaborate? Is it possible to structure programs without dynamic OOP?

Collapse
 
m0n0x41d profile image
Ivan Zakutnii

Your joke even better than my ;D

Collapse
 
syeo66 profile image
Red Ochsenbein (he/him) • Edited

This post is just a joke, right? Right!?!

Collapse
 
totalian profile image
totalian

This is a pretty good start at simplifying the code. However, as a true senior dev - I would take this a step further implement a basic microservice architecture. As the program is not too complex the code could probably be refactored into only a few hundred independent services.

Finally, I would somehow manage to include Docker and Kubernetes in my solution. As every senior dev knows, your code is not truly simple if you can't somehow incorporate Docker containers.

Collapse
 
brock_chestwall profile image
Brock Chestwall

I hope to follow up with some nuggets of hosting wisdom. Kubernetes (or K8s for short) can get a bad rap– but ultimately it's the only way to grasp the helm of virtualization.

Maybe a future article can help scratch your curiosity itch

Collapse
 
syeo66 profile image
Red Ochsenbein (he/him)

And don't forget to include Kafka. It really calls for it.

Collapse
 
svidlak profile image
Max Svidlo

Over abstraction of code is a pain in the butt on the long run.
If I need a thing to do a thing I just write the thing, no more and no less.
Writing a bunch of classes with a single method just complicates things eventuall

Collapse
 
andreasoverland profile image
Andreas Øverland

I believe the author when he writes "Here's how a senior developer would code this..."

A beginner may write the first bit of code in this article : It does the job it's supposed to do. No more, no less. And there are even comments in the code that explains everything. It is in fact the very definition of clean and simple.

Along comes a "senior" developer with 2 years of experience and a tool belt full of fancy frameworks they barely have any experience with. And what's more important than frameworks? In the mind of a "senior" developer : Nothing. At least not the users and/or customers needs. So a "senior" developer may very well produce the unreadable jungle of unmaintainable spaghetti code that the author suggests.

Now, when an expert developer, with say 10,15 or 20 years of experience wants to write a program that does the same job, my "guess" is that the result will look exactly like the first version. Clean, minimal and easily replaceable.

So ether this is a joke, a troll-post by a newly registered account, or it is written by a "senior" developer in a fast moving tech job. And I can only assume that the author means that a developer who writes code like this has to move jobs a lot, and fast.

PS : I do like posts that make us think twice.

Collapse
 
decker67 profile image
decker

That seems not to be any simpler at all.

Collapse
 
brock_chestwall profile image
Brock Chestwall

Looks can be deceiving, but beauty is in the eye of the (developer) beholder!

Collapse
 
tiguchi profile image
Thomas Werner

I like that you refused to add an "/s" in the end. Well done! 👏

Collapse
 
manchicken profile image
Mike Stemle

I feel like your hashtags could use to read this opinion piece I wrote: dev.to/manchicken/ninja-rules-of-s...