3 ms·
After climbing for a while, I went down the ladder from whence I started and try to use fewer features to do more. My code aims for reusability by cut and paste
by buzzybee 10y ago
After climbing for a while, I went down the ladder from whence I started and try to use fewer features to do more. My code aims for reusability by cut and paste as the first step - not as the end point, but as an important validation of whether the implementation can actually stand on its own as a drop-it-in block of code, not reliant on tricks or external dependencies. When I want to refactor my first step is to inline code and data until it cannot be inlined further, so that new approaches for reuse appear.
Simultaneously, I started aiming more and more precisely towards a higher "level of completion" in abstracting. When I want to abstract heavily, I do not reach for an abstraction-shaped-syntax within the language and make my abstraction fit their abstraction; I write a compiler, and write the actual thing I want, with the type system, internal behavior, and error checking I want. And it takes a month or more, sometimes, but then I have something far more valuable to my codebase than a general purpose tool. This does not happen often; the compilers exist as part of an ecosystem. Most of the things that seem "DSL-like" can be couched in terms of reconfiguring an existing compiler around new APIs.
I have very few debugging problems within application code; most of my time is spent either on data modelling, or compiler maintenance.
We do not know what good code looks like. We do not know what bad code looks like. We know only that we are progressing slowly or encountering a lot of bugs, and some of those issues are related to the shape of the code.
- chriswarbo 10y ago> When I want to refactor my first step is to inline code and data until it cannot be inlined further, so that new approaches for reuse appear. I do a similar thing. My first attempt is usually full of layers of helper functions and not-quite-right abstractions as I was simultaneously trying to understand and solve the problem. Once I've got something that works, I refactor it to collapse these layers and remove the bias introduced by my previous fumbling. Inlining reduces external references, and point-free style eliminates local references ( https://wiki.haskell.org/Pointfree https://wiki.haskell.org/Pointfree ). After such a refactoring, the code is dealing much more with inescapable features of the problem, rather than fighting against itself. At this point, I can do a final cleanup to introduce abstractions to reduce redundancy and aid understanding.