Description
The Code
object appears to have an implementation that makes it rather rigid and difficult to work with. It inherits from a class that makes it rather confusing, given that it is in the text
namespace, and it seems to have an implementation that breaks several design principles that would help to improve its maintainability and possibility for reuse in other modules and packages.
I would like to propose a refactor or implementation of the module code_mobject
from which it derives. I have several suggestions that would serve as a starting point for discussion.
Before I continue, I just want to note that my primary experience in software development lies in other languages where things are done differently from what may be standard in Python. Additionally, I am not entirely familiar with the Manim library at large, so I hope I have not ignored intentional design choices due to some particular reason.
Observed issues
The interface
Problem
This problem is hard to describe and propose a single solution to, so I would like to motivate you with an example.
Suppose I wish to start off with a simple animation between these two code blocks, read from two files. I would like to use something like TransformMatchingTex
, but unfortunately, Code
is not compatible.
A second example is showing/fading in one line (or word) at a time. I have been told there are "invisible dots", and so steps have to be taken to perform this task. The Code
object does make life a lot nicer, providing code highlighting, but there is an additional boilerplate surrounding its use that can likely be reduced.
Proposed solution
I admit that Python is not my strongest, most fluent language, so I do not have the skills to claim my way is a sound solution. So, what I suggest may not be best suited for Python.
I would suggest a form of adaptor interface or some other structural design pattern that best allows the user to interact with Code
as if it were a text-like object. I am not sure what would be the best approach, since it makes sense to treat Code
as a group. Yet, being that is it a complex structure by nature, not having the powerful tooling available to other text objects makes it difficult to use.
An alternate solution comes from the solution to the following problem.
Too much responsibility
Problem
The Code
object has a lot of responsibility. For example, it is able to generate HTML and JSON. The latter of which takes up almost 100 lines of code, or around about 15% of the file. Furthermore, the particular method responsible for generating the JSON is littered with several commented-out print statements, which would indicate a form of debugging that was never removed.
Another detail is that the constructor generates a background from within its own class. Again, by employing the solutions listed in the next section, a user can design their own background and pass the code to it to use.
Proposed Solution
A refactoring of the class, in short. Firstly, putting the Background, HTML, and JSON generators into their own concrete class (with their own interfaces) allows you to implement a behavioural design pattern, such as the strategy or visitor pattern. This additionally allows for other generators to make use of and consume the Code
class, were they ever needed to be made.
Secondly, and related to the previously listed problem, a refactor of the class, with the generators taken outside the class's responsibility, the class can be modified to better incorporate other interfaces. As mentioned earlier, if the Code
class were to be believed as being able to be animated just as flexibly as other objects, then, since it is complex in nature, another interface may better suit the object. This would provide users with a means to interact with elements that compose the object's structure, which is currently rather difficult to do in complex cases.
As an example, suppose I had a Code
object. Perhaps a code.get_word(5)
returns a view of the 5th word. Or, if I want a line, code.get_line(3)
. These needn't necessarily return the internally maintained objects/strings/tex objects. It might make sense to instead return an object that would expose those lower-level components as an animatable object, which allows you to transform and animate the individual components as if they were. I say that since I do not fully understand how everything works beneath the Code
object layer. For example, it may be difficult to build a more complex object to provide a better way to animate composed units, such as words, while being able to provide adequate syntax highlighting throughout the animation. Hence, exposing these units (e.g., a word) to be animated or modified (such as for overriding the syntax colour highlighting with something like .set_fill()
) would encapsulate the state of that unit, and only expose the necessary tools for animating or modifying that unit.
I want to further describe that last point. Suppose you stored each word individually. Rather than returning a Tex
object, or some other such object, you may return something else that allows the object to be consumed by the user. Now, I am not sure how this would be done in Python, so I may be coming across as ignorant, so I do apologise. In a language such as C#
, you could return the type by an interface
. So, a text-like object may have an IText
interface, but you instead return the object as an IAnimatable
, which changes how the user can interact with it. In Python, this "idea" may be done functionally, as much of Manim already is, such as by taking functions as arguments.
In closing
The Manim library is inherently a mathematics library and a Code
object is something valuable given that there are many areas of STEM that overlap with mathematics, and so the Code
class allows folks to incorporate the software side of mathematics into their animations.
I would like to motivate the discussion on extending this part of the Manim library, as it would be very helpful and useful for enhancing the creative possibilities of users by reducing the amount of work and confusing kinks they have to manage themselves.
I would love to have the opportunity to work on this myself, but unfortunately, I am unable to give my attention to this until closer to the end of the year. Assuming this is not addressed, I may very well do so then. For now, I would love for the discussion to begin, in the hopes that there are others out there like me, who would much appreciate using the library to present software animations.
Again, I apologise if I was off with any ideas or suggestions, not having the full understanding I require to properly achieve what I would like to suggest. I have had only a few weeks and limited time to learn the library's source, in the hope of using it for a project, but I ran out of time trying to get the Code
object to behave in the way I would like. I did make some good progress, so I do hope my other experiences have allowed me to correctly translate my ideas in a manner that describes good and approachable ideas.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status