-
Notifications
You must be signed in to change notification settings - Fork 1
Description
I thought this might be helpful to others - here are some of the lessons I learned and insights from working with the Less codebase:
-
Code Documentation - It is fairly poor. A lot of figuring things out requires a good deal of forensics. How/why things are the way they are is often not clear. I'm probably party to that - you tend to adopt the pattern given in a codebase. When you're working on a section with no documentation, putting in a large JSDoc can feel odd. But that should probably not be the case.
-
High abstraction - There are a lot of abstracted layers that allow for a high level of theoretical extensibility, but being undocumented, a lot of that theoretical extensibility will never be utilized. For instance, it looks like Less can have X number of file managers and even URL managers per system per directory per filename. And Less can have Y number of environments that encapsulate those? Less creates instances of classes that are only used once, but, in some cases, because of the way the prototype objects are exposed, creates more than one instance when only one is needed. In that sense, it almost resembles a Java API vs. a compiler whose job 99.99% of the time will be to run once and be done.
-
Strict program flow - Despite a lot of environment extensibility, the way nodes are parsed and evaluated is fairly rigid. This prevents things like incremental parsing / evaluation (not that that's a huge deal, but has been brought up in the past).
-
Nodes are both smart and dumb - Nodes hold data, and are visited with a visitor pattern (so are almost like a plain AST), but they contain lots of methods to self-evaluate their own nodes, but ALSO they are unable to fully do that without being passed in the context in which they reside. All of this makes for code that's hard to reason about, but it also makes a simple API for those nodes impossible. You can't call
toCSS()
on a node. You have to pass in context, even though that node is an instance which has a fixed context. So there's a lot of pushing / pulling of data flow in the process of node evaluation. Sometimes things act on nodes and modify them; sometimes nodes act on themselves and push data out. From a JS performance standpoint, it also means that many node instances are modified from their original prototype, so a JIT engine is unlikely going to be able to optimize them. -
Some inconsistency in patterns - This is probably to be expected with open source, but in some cases, Less uses a callback pattern, and in other cases, Promises. Probably the above evolution of nodes is likely related.
-
Ghost code - There are probably irrelevant or unused options or sections of code that is just legacy stuff. Like I know chunking was removed as the default at one point?
Despite that, it doesn't take terribly long to do things, but there were lots of cases where I wish I'd known a pattern / interface already existed in the codebase, or times when I just never could fully grok how a section of code was intended to be used, no matter how much I looked at it.
I don't have any recommendations, but perhaps some recommendations could come out of this? It's worth opening for discussion, IMHO.