3 ms·
I think it is important distinguish the necessary from accidental complexity. Macros are typically more difficult to understand but if done well that would be
by lmilcin 6y ago
I think it is important distinguish the necessary from accidental complexity.
Macros are typically more difficult to understand but if done well that would be because they are sinking complexity from a bunch of code.
For example, if a macro implements variations of repeating construct, you are removing those variations from your entire codebase and putting complexity of dealing with that into a single macro.
Now, the issue is when you start creating accidental complexity.
For example, there are various techniques that reduce overall complexity just by being consistent in how you do things. Using only hygienic macros or writing macros consistently in a way that allows the reader predicting what they do reduces a lot of perceived complexity.
If the reader of the code does not have to understand the macro to be able to more or less predict what it does and what are basic guarantees it provides, it reduces a huge amount of complexity when you try to read and understand.
If writing a macro can be compared to writing an operator in a language then all other language design rules apply. It would be a bad language that constantly surprises the user.
Unfortunately, Lisp code tends to be much more abstract with lots of complex, custom operators (macros) as building blocks. If these building blocks are not clear and cannot be relied upon (ie. you don't understand how they work and can't predict what they will do) then this is much more damaging to trying to understand how the codebase works than writing unclear functions.
- lispm 6y ago> sinking complexity from a bunch of code Sometimes macros provide domain-level constructs. This creates very dense code - which can improve code understanding. One thing I would recommend to put extra effort into macros, especially with these aspects: One should write documentation what the macro expects and what it does. This way this has not to be inferred from reading the often quite complex code. Document the implemented syntax. The macro should check the syntax of the forms. Provide error messages for rejected forms.
- mumblemumble 6y agoWith those things in place, macros can absolutely be a net positive for code understanding. And if I saw that being done with any regularity at all, that would be great. As I get older and more jaded, though, am coming to think that, in an office setting, it is a mistake to choose a language is optimized for maximizing the effectiveness of a thoughtful programmer. It's much more valuable to minimize the damage that can be done by a careless programmer. One of the most sobering realizations of my career was that the most effective way to become your team's 10X programmer is not to work in a way that lets you be 10X more efficient than your colleagues. It's to work in a way that forces your colleagues to be 10X less efficient than you.
- lmilcin 6y agoThat is exactly what I have realized after decades of work. There is a cap on how much work you can do individually. There is no cap on how much damage or improvement you can cause to other people you work with. It does not matter how clever you are with your code if nobody else is going to be able to continue that work or support its results. For this reasons I have developed following, informal rules I try to follow: 1. It is ok to be clever with the code if I am going to be only one to ever read or use it. This can assumed to be always false for production code. I limit my cleverness to PoCs, adhoc tools and emergencies. 2. Always think how other, and especially junior members of the team are going to develop and support my product. Is it too complex for them to follow? Is there something that can be done so there is less chance they are going to misuse it? 3. I use my cleverness to try to develop simpler and more reliable products. Simplicity is defined by how much work junior member of the team is going to have to expend to understand it. Reliability is defined by how likely it is to fail in face of junior team members operating / developing the piece of code. 4. If team members have trouble understanding or working with my products it is always my fault. Figure out how to make the product simpler or at the very least provide training and ensure they understand how it works.