7

i had an epiphany today, in a discussion with the software architect of our new project.

i'm having the epic job to design & implement a prototype for a C++ library in a new software project and collected some inspiration in our "old" software, where i'm maintaining the module that fulfills the same functionality (i thought). i've been maintaining this module for around a year now. i analyzed the different features and stuff to consider and created a partial model of the new library.

when i showed it to the architect today, he was like "oh my god, no no no, you don't need all this functionality, this shall not be part of the new library!"

this was the moment when i realized how deeply fucked up the code base of the old module is.

imagine it like this:
you want to automate the process of making yourself a good ol' cup of coffee.
the reasonable thing would be to have

- a smart water boiler where you set parameters water temperature and amount of water to be fetched from the water supply
- a smart coffee bean grinder where you can set type of beans, amount of beans and grinding fineness
- a component where water and ground coffee are joined to brew the coffee, where parameters like duration, pressure etc. are set
- a milk tank where amount of milk, desired temperature and duration / speed of foaming can be set
- a sugar dispenser where amount of applied sugar can be set
- optionally, additional modules with spices, syrup, ice cubes, whatever for your very personal coffee experience

on requesting a coffee, you would then configure and orchestrate all components to your wishes to make you a fine cup of coffee. you can also add routines like "makeCappucchino()", "makeEspresso()", or whatever.

our software is not like this.
it is like this:
- a smart water boiler consisting of submodules that know how to cook water for e.g. "cappucchino with sugar" or for "espresso without sugar, but with milk and ice cubes"
- 5 smart bean grinders that know how to grind beans for e.g. cappucchino, espresso, latte macchiato and for 73ml of water preheated to 82°C
- a very smart sugar dispenser that knows how to add sugar to 95, 98 and 100°C coffee and to coffee made of BOTH coffee arabica AND coffee robusta beans.

etc. etc., i think you're getting the gist.

when i realized this, it was like, right in front of my eyes, this terrible pattern emerged like a foul, corrupted caleidoscope of chaos, through the whole code base of this module.
i've already known how rotten from the core this code base is, but today i've actually identified a really bad pattern that i hadn't realized before. the whole architecture is so bloated that it is hard to have an overview of the whole thing. and it would require a LOT of refactoring to repair this pattern.
but i guess it would also be infinitely satisfying because i could probably reduce the code base for 30% or something...

but unfortunately, this is never going to happen, because screw refactoring.

it's a great feeling to start this new library from scratch, tho...

Comments
  • 3
    If that had been one of "my" codebases, one of the coffee programs actually would have launched a disinfection mode using some chemicals, but with no further indication. :)
  • 1
    @Fast-Nop interesting... and this "disinfection" mode is only activated when your worst enemies happen to make themselves a coffee?

    "adding insoluble and slightly bitter but otherwise completely unsuspicious sugar crystals to coffee, thank you for your order, beep boop"
  • 1
    @Fast-Nop "oops i mean, no further indication, beep boop"
  • 1
    @soull00t Either that, or the first customer tester who happens to randomly try out some stuff. ^^
  • 3
    I can simplify your example.

    You want to export from a database to an CSV.

    Database - let's say your language has a native wrapper

    CSV - let's say your language has a native interface

    Now any sane person would do the logical thing: database - database wrapper - simple representation of objects (arrays / list / map whatever you call it) - CSV interface - done.

    It's logical. It's simple. You might have to compromise a bit, but it is sufficient.

    May I present you what I've seen instead...

    ORM | Gateway | Repository | DataMapper
    - DTOs / Entitys / Value Objects
    - Export Interface
    - Export Value Format Interface
    - Export Implementation
    - Export Storage Interface
    - Export Storage Driver
    - Export Storage Implementation
    - Logging Implementation
    - Notification Gateway and event handling to get notification when it's done
    - HTTP API for download and queuing exports
    - ...

    I could go on.

    But yeah. Originally the task was: Create a CLI application -/ function that takes data from database and outputs it to the local storage in CSV.

    That was everything.

    I've seen things. Terrible things.
  • 2
    @IntrusionCM "Now any sane person would do the logical thing"
    hehe, we don't do that here..

    can relate a lot... 😂
Add Comment