justingardner / mgl

A suite of mex/m files for displaying psychophysics stimuli
http://justingardner.net/mgl
Other
18 stars 22 forks source link

Explicit command model in the Metal app #69

Closed benjamin-heasly closed 1 year ago

benjamin-heasly commented 2 years ago

This is a suggestion for some refactoring we might want to do in the Metal app, to extract an explicit, object-oriented "Command Model" in the Metal app code. I'll outline some what I think we'd do, and why I think it would help.

I also started sketching this out in the Metal code here. So far this is just comments, nothing functional.

The Command Model itself would be a way to capture patterns that are emerging in the code of our mglRenderer. We have a bunch of command codes coming from Matlab, and each seems to be associated with a fairly consistent set of properties and behaviors:

The Command Model could be a Swift protocol, perhaps mglCommandModel, which would capture these operations as required and optional methods. We'd be able to refactor the mglRenderer to depend on this protocol, but not on the implementation details of each individual command. We'd also be able to move the implementation details of each command into a separate file.

One immediate benefit of this refactoring would be to make the code easier to read an understand. mglRenderer is currently >1000 lines and mixes concerns like flow control, socket/command interface operations, and the state and implementation details of individual commands. Extracting the commands would reduce the code in mglRenderer and clarify its responsibilities. It would also make each individual command easier to understand by grouping related, coupled behaviors into cohesive units/files.

This could also set us up to achieve future goals.

We've started introducing "repeating" commands as in #67. These may be a first step towards other, more complex commands that run "close to the metal" and don't require frame-by-frame socket communications. As these commands grow in complexity it seems likely they will need to maintain data, like texture or vertex buffers, across multiple frames, and may have state that changes between frames, like counters or behavior flags. An mglCommandModel implementation would be a natural place to store these things. Currently we don't have great place for these things, except to add on to mglRenderer.

We've talked about the possibility of making our Metal app extensible by runtime plugins. If we go this way, we'd need to define a protocol/interface against which plugins could be written, and loaded by the app. Something like mglCommandModel could fill this role.

Even if we don't go all they way to runtime plugins, it could be useful to know exactly what it takes to create a new command. A command author/contributor could focus on these things, and not have to think about other moving parts of the app, and could have some confidence that things going on within the new command are not likely to break other existing commands or parts of the app.

Currently, our informal commands "instantiate" themselves by reading from the mglCommandIngerface. We don't currently have another way to instantiate a command, which means it's hard to test the app without mglCommandIngerface and Matlab in the loop. If we had an mglCommandModel and implementations of this protocol, we could instantiate them directly from test code, and add a suite of standalone tests to the Metal app to be run directly in Xcode. This could shorten dev-testing cycles and help isolate issues.

justingardner commented 1 year ago

This seems like a really good idea, but I'm going to close for now as I don't think we have to plan to implement in the near future. When we come back to this, we can reopen the issue.