4 ms·
Thank you for writing this. I've come to exactly the same conclusion after a decade of building and delivering complex tangible applications which others have t
by oldboyFX 4y ago
Thank you for writing this. I've come to exactly the same conclusion after a decade of building and delivering complex tangible applications which others have to maintain after I'm gone.
- fleddr 4y agoThanks for the support. I used to live all the best practices, but over time learned that the number one enemy in a codebase is complexity. 90% of software development is maintenance. People doing maintenance are lowly productive because the vast majority of time is spent on trying to understand how things even work, debugging, and making changes in a way that is safe. The reason code is complex are abstractions and dependencies. Many of which are of a questionable or negative value and never deliver their imagined benefits. Hence, instead of "abstract by default" and seeing DRY as some religion, I abstract when value is real, proven and outweighs the massive downsides of doing so. Imagine that we'd need to write a recipe. Sane and pragmatic people would write it as a sequential step of instructions. If a software engineer were to write one, just to follow the recipe you'd need to have 23 additional papers each describing a sub step referred to from the main instructions. Next, we would abstract each substep into "Motion" and "Activity" generalizations. This way, you can reuse "Motion" when you walk your dog later that day. Quite obviously, motions can fail so we extend it with a MotionError, which is a sub class of Error. MotionError has a Logger interface. These 3 super abstractions are useful, instead of just directly saying that you failed a recipe step, we can now apply failure wherever we want, even onto life itself. Since recipes are written in a language, we should abstract Language, itself a composition of sentences, words, characters and glyphs with a Dictionary interface, which itself is an array of Name and Value objects, that we might as well generalize as Thing. Anyway, those were recipe steps. Next, let's do ingredients, also known as immutable multivariant singletons. But not really, because as we follow the instructions, the ingredients morph into something else, which we'll solve with a Morp object, which holds an interface StateChange, consisting of two State objects, which are Things. A ThingsIterator takes care of handling multiple things but not in a way you'd expect, we'd override map() because I really feel my Thing is special. Thinking of recipes, they can potentially come from any source so we'll implement Verbal (an abstraction of Language), Database and the jungle that comes with it, all neatly wrapped into MoreThings. Next we redo all of his by writing unit tests, so that our software that by now implements most of the universe is qualitative. It's math. Or...we can just write the damn recipe.
- zabzonk 4y agoagreed with your first post, much less so than this one, because it is based on analogy. recipes are really not like programming. when i try a new recipe, i normally read the description to see what i am going to get out of it, and if it appeals, give it a bash, without any accuracy. for example, elizabeth david (never a one for accurate measurements) has a great recipe for beef with olives, which comes down to onions, garlick, bay leafs (other herbs to taste) olive oil, lemon peel, beef, black olives, red wine. then just cook them. any experienced cook will have no probs with this - the interesting thing is the combination of beef and olives. all the quantities are somewhat irrelevant and can be adjusted to taste. whereas a computer program must be pin-point accurate in all details analogies == bad. imho sorry i went on a bit there
- john_the_writer 4y agoTell me you've never cooked for your mother-in-law without saying you've never cooked for your mother-in-law :)
- tome 4y agoIt’s funny because I completely agree with you principles but completely disagree with, what I think is, your conclusion, that functional programming should be eschewed. On the contrary, pure FP, specifically in Haskell, is the only way I’ve ever found to reliably put your principles into practice.
- fleddr 4y agoI honestly didn't even realize that I had principles. I find them too abstract.
- naasking 4y agoYour beef appears to be with over-abstraction and not functional programming. FP generally makes debugging much easier because the state of the system isn't changing in unexpected ways underneath you, so you only need to look at local state. A "functional" recipe is just as simple and straightforward as an "imperative" recipe. Over-abstraction on the other hand, can be introduced with imperative object oriented programming just as easily as with functional programming.