La mayoria de los interfaces de usuario tiene un botón de deshacer acción, y otro de rehacer lo deshecho. Hasta mi sentido común me dice que es una buena idea.Buscando por ahi, he encontrado varios modelos de implementación:
  1. Command pattern, que consiste en encapsular las acciones en clases
  2. Memento pattern, que si entendí bien consiste en que un portero(caretaker) solicite y restituya estados a una clase de trabajo
Entiendo que las aplicaciones con manejo de gran volumen de datos deben usar un registro de acciones, y no de estados, ya que el consumo de memoria se podría disparar. Por otra parte, la intuición me dice que es más costoso implementarlo con acciones que con estados... tengo poco tiempo pero tampoco quiero hacer algo que no se pueda usar con muchos datos ¡Que dilema!

La verdad es que a mi esto me recuerda a la diferencia entre las máquinas de Moore y las máquinas de Mealy.
Um... yo empezaría pensando qué cosas se tienen que poder deshacer en la aplicación. Así, por encima, yo veo 4

    * Cambios en los datos de la tabla [imprescindible]
    * Cambios en la definición de los campos [imprescindible]
    * Cambios en las propiedades de vista (altura de las filas, filtros, ordenación, etc) [mola, pero no imprescindible]
    * Borrar y crear llamadas a R (hacer gráficas, análisis, y cualquier cosa que se cree código R para hacerlo) [también, pero es igual de prescindible que lo anterior]

La diferencia principal que yo veo entre los dos patrones de diseño que encontraste es que en el «command pattern» tienes que implementar la pareja undo/redo para cada acción;

Mientras, en el «memento pattern» basta con hacer que los objetos editables (como la tabla de datos o la de definición de columnas) sean estados por sí mismos, y te bastaría con apilar una copia del mismo antes de cambiar. De manera que deshacer una acción sólo sería sacar el objeto de la pila y ponerlo en su sitio (colocando el que estaba en la pila de rehacer y blablabla)

Decidir no es trivial, pero pensandolo un poco, viendo pros y contras e historias, yo creo que la mejor opción es el patrón de memento con un pequeño retoque.

Sin duda, lo más cómodo con diferencia es guardar estados (tu intuición no te falla) pero está el problema del crecimiento del consumo de memoria:

    * Para el caso de la definición de columnas casi que da igual, porque no es algo que se cambie muchas veces y tampoco consumirá mucho (por ejemplo, suponiendo 100 bytes por columna, una tabla de 15 (que no son pocas) columnas sólo requeriría ~1,3Kb por cambio, lo cual es insignificante)
    * Para la tabla de datos sí es más importante... sin embargo, una optimización muy simple y efectiva es que el estado sea un diferencial.. o sea.. que en lugar de guardar toda la tabla, guardes sólo las celdas que han cambiado (que sería simplemente las coordenadas del área cambiada (por si es una acción de copiar y pegar que afecte a varias celdas a la vez) y los datos que se han copiado). Con eso ya tendrías las ventajas de tener estados sin tener que gastar memoria salvajemente.. aunque tendrías que picar un poco más, para tener en cuenta el diferencial.