Hello everyone.
I wish to do some refactoring on a class widely used by some of my views. The refactoring consists in renaming the class WindowBackPainter, making it a subclass of a new abstract class ViewPainter, pushing up some of it's intance variables and methods, removing others and changing some of it's publishedAspectsOfInstances. I have already done many views that have an instance variable holding an instance of WindowBackPainter, and I've read in the archives that doing this kind of changes on Views can result in a headache. For what i've read, my alternatives are: - increase the version number of WindowBackPainter class, and write the stbConvertFromX: to make old instances become new ones. - open every view that holds a WindowBackPainter, refactor, and save them again. Am I making a problem out of nothing, or this kind of refactoring really are problematic ? What would you say is the simplest way to deal with this ? Thanks in advance. Martin |
Martin,
> I wish to do some refactoring on a class widely used by some of my views. > The refactoring consists in renaming the class WindowBackPainter, making it > a subclass of a new abstract class ViewPainter, pushing up some of it's > intance variables and methods, removing others and changing some of it's > publishedAspectsOfInstances. Afterward, you might want to assign a global named WindowBackPainter that points to the renamed class. You will still have to keep the STB versions correct, etc. > I have already done many views that have an instance variable holding an > instance of WindowBackPainter, and I've read in the archives that doing this > kind of changes on Views can result in a headache. Is WindowBackPainter not a View subclass? If it is indeed not, then STB versioning, as you describe below, if probably going to be sufficient. Note that you might want to load/save all of your view resources to avoid their invoking the conversions every time they are reloaded. They will do it happily (if it all works), but you can avoid any resulting inefficiency by resaving. > For what i've read, my alternatives are: > - increase the version number of WindowBackPainter class, and write the > stbConvertFromX: to make old instances become new ones. Don't forget the boiler plate #stbConvertFrom:. Incremental conversions are they way to go. > - open every view that holds a WindowBackPainter, refactor, and save them > again. > > Am I making a problem out of nothing, or this kind of refactoring really are > problematic ? What would you say is the simplest way to deal with this ? > Thanks in advance. You appear to be on top of it; either should work. My recommendation is to make a backup and try the STB conversion; then open and resave views (both as a test and for efficiency in the future). Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill, I will try the STB conversion as you recommened.
I haven't thought about the global poiting the new class nor about loading and saving all my views at once after increasing the version. This will let me definitly forget about the versioning. Thanks ! Martin "Bill Schwab" <[hidden email]> escribió en el mensaje news:cte6sf$r5a$[hidden email]... > Martin, > > > I wish to do some refactoring on a class widely used by some of my views. > > The refactoring consists in renaming the class WindowBackPainter, making it > > a subclass of a new abstract class ViewPainter, pushing up some of it's > > intance variables and methods, removing others and changing some of it's > > publishedAspectsOfInstances. > > Afterward, you might want to assign a global named WindowBackPainter > that points to the renamed class. You will still have to keep the STB > versions correct, etc. > > > > I have already done many views that have an instance variable holding an > > instance of WindowBackPainter, and I've read in the archives that doing > > kind of changes on Views can result in a headache. > > Is WindowBackPainter not a View subclass? If it is indeed not, then STB > versioning, as you describe below, if probably going to be sufficient. > Note that you might want to load/save all of your view resources to > avoid their invoking the conversions every time they are reloaded. They > will do it happily (if it all works), but you can avoid any resulting > inefficiency by resaving. > > > > For what i've read, my alternatives are: > > - increase the version number of WindowBackPainter class, and write the > > stbConvertFromX: to make old instances become new ones. > > Don't forget the boiler plate #stbConvertFrom:. Incremental conversions > are they way to go. > > > > - open every view that holds a WindowBackPainter, refactor, and save > > again. > > > > Am I making a problem out of nothing, or this kind of refactoring really are > > problematic ? What would you say is the simplest way to deal with this ? > > Thanks in advance. > > You appear to be on top of it; either should work. My recommendation is > to make a backup and try the STB conversion; then open and resave views > (both as a test and for efficiency in the future). > > Have a good one, > > Bill > > -- > Wilhelm K. Schwab, Ph.D. > [hidden email] |
Martin,
> Bill, I will try the STB conversion as you recommened. > I haven't thought about the global poiting the new class nor about loading > and saving all my views at once after increasing the version. This will let > me definitly forget about the versioning. I'm not sure what you mean. With the global, I am assuming that you will still version the changed class, because the serialized instances will have the old instance variable layout and the old version number. All the global does is allow them to work after the rename - and I've never actually tried it :) Make a backup first and have fun. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Martin Rubi
"Martin" <[hidden email]> wrote in message
news:[hidden email]... > Hello everyone. > > I wish to do some refactoring on a class widely used by some of my views. > The refactoring consists in renaming the class WindowBackPainter, making > it > a subclass of a new abstract class ViewPainter, pushing up some of it's > intance variables and methods, removing others and changing some of it's > publishedAspectsOfInstances. > > I have already done many views that have an instance variable holding an > instance of WindowBackPainter, and I've read in the archives that doing > this > kind of changes on Views can result in a headache. > For what i've read, my alternatives are: > - increase the version number of WindowBackPainter class, and write the > stbConvertFromX: to make old instances become new ones. > - open every view that holds a WindowBackPainter, refactor, and save them > again. > > Am I making a problem out of nothing, or this kind of refactoring really > are > problematic ? What would you say is the simplest way to deal with this ? > Thanks in advance. During development by far the simplest option is to open all referencing view resources in View Composers. Then make your changes, and resave all the edited views. For many shape changes you won't need to do anything else since the system's normal instance migration capabilities will do all that is needed, but you may have to patch up some of the open instances depending on how you approach it, e.g. you might add new instance variables that you need to initialise. When I get a chance I'll post up a little script that opens VCs on all view resources that either contain instances of a a particular class or which reference it in some other way. You only need to bother writing STB conversions when there are pre-existing view resources that you can't load up, or in cases where you don't know whether any resources in packages you do not have loaded might contain such instances. Assuming that you aren't developing classes that are used in other projects, it is possible to avoid the need to write STB conversions at all if you are careful. If you do need to write STB conversions, then typically this is straightforward, particularly if the class you are modifying has no subclasses. Things get more complicated when one modifies a class with subclasses where one or more of the subclasses have their own pre-existing STB conversions, but it can be managed with care. You can find examples of differing levels of complexity of conversion, and different approaches, in the standard image. A useful tip when renaming a class is to create an aliasing global that retains the old name to the class. The package system recognises such aliased class names and can store them correctly. Regards Blair |
Blair McGlashan wrote:
> During development by far the simplest option is to open all referencing > view resources in View Composers. Then make your changes, and resave all the > edited views. FWIW, this _type_ of approach also works when saving models to file using STB. In particular, I use alot of shells descended from DocumentShell, which has builtin #fileSave that uses STB. If I make a change to my model definition, i.e., add/remove instance variables, I will first open an instance of my app on each saved model file (during development there's usually only one or two), then make the class definition change and then save each model file. That allows me to avoid defining stb version methods. As Blair pointed out, one thing to remember is that the state of new variables will be nil, so if the model expects a non-nil value, I'll set these values by hand (or define a lazy accessor) before saving things back. E.g., let's say I add a boolean instance variable named isSomething to the model. In the model's #initialize method I'll add a line like isSomething := true. Then, in a browser, I'll execute something like MyModel allInstances do: [:e | e isSomething: true] and then do a #fileSave. -- Louis |
In reply to this post by Blair McGlashan-3
Hello Blair.
Your explanations are very clear, thanks a lot. So, if I understood correctly, opening all the involved Views during the refactoring and saving them back again will be enough. Since suspect I will want to do this same procedure quite often, I have done a tool to let me select the resources I will want to keep opened during the refactoring. The tool is very raw and I think it needs some more work, but I've tested a little and the results were good enough for me. I can now open a shell that let's me filter resources by packages and classes, then select some or all of them and load them without actually opening any ViewComposer. Then, when I'm done changing things, I can just save them or unload them all, and that's it. Currently I'm using it to load every resource in every package of my own. It's not sutil, but I'm sure every view is updated this way. If anyone is interested in this incipient tool, let me know and I'll just send it. Regards and thanks again. Martin > > Hello everyone. > > > > I wish to do some refactoring on a class widely used by some of my views. > > The refactoring consists in renaming the class WindowBackPainter, making > > it > > a subclass of a new abstract class ViewPainter, pushing up some of it's > > intance variables and methods, removing others and changing some of it's > > publishedAspectsOfInstances. > > > > I have already done many views that have an instance variable holding an > > instance of WindowBackPainter, and I've read in the archives that doing > > this > > kind of changes on Views can result in a headache. > > For what i've read, my alternatives are: > > - increase the version number of WindowBackPainter class, and write the > > stbConvertFromX: to make old instances become new ones. > > - open every view that holds a WindowBackPainter, refactor, and save > > again. > > > > Am I making a problem out of nothing, or this kind of refactoring really > > are > > problematic ? What would you say is the simplest way to deal with this ? > > Thanks in advance. > > During development by far the simplest option is to open all referencing > view resources in View Composers. Then make your changes, and resave all the > edited views. For many shape changes you won't need to do anything else > since the system's normal instance migration capabilities will do all that > is needed, but you may have to patch up some of the open instances depending > on how you approach it, e.g. you might add new instance variables that you > need to initialise. When I get a chance I'll post up a little script that > opens VCs on all view resources that either contain instances of a a > particular class or which reference it in some other way. > > You only need to bother writing STB conversions when there are pre-existing > view resources that you can't load up, or in cases where you don't know > whether any resources in packages you do not have loaded might contain such > instances. Assuming that you aren't developing classes that are used in > other projects, it is possible to avoid the need to write STB conversions at > all if you are careful. > > If you do need to write STB conversions, then typically this is > straightforward, particularly if the class you are modifying has no > subclasses. Things get more complicated when one modifies a class with > subclasses where one or more of the subclasses have their own pre-existing > STB conversions, but it can be managed with care. You can find examples of > differing levels of complexity of conversion, and different approaches, in > the standard image. > > A useful tip when renaming a class is to create an aliasing global that > retains the old name to the class. The package system recognises such > aliased class names and can store them correctly. > > Regards > > Blair > > |
"Martin" <[hidden email]> wrote in message
news:41fe4c71$[hidden email]... > Hello Blair. > > Your explanations are very clear, thanks a lot. > > So, if I understood correctly, opening all the involved Views during the > refactoring and saving them back again will be enough. It will be enough to ensure that any schema changes you make that can be applied through the standard schema migration performed by the ClassBuilder are reflected in the resources as well as any other instances. What this means is that the shape of the objects will be correct after the change, but it doesn't necessarily mean the objects will be valid. For example you might introduce new instance variables; these will be nil in any pre-existing instances, which might not be a valid state for the object. > > Since suspect I will want to do this same procedure quite often, I have > done > a tool to let me select the resources I will want to keep opened during > the > refactoring. The tool is very raw and I think it needs some more work, but > I've tested a little and the results were good enough for me. I can now > open > a shell that let's me filter resources by packages and classes, then > select > some or all of them and load them without actually opening any > ViewComposer. > Then, when I'm done changing things, I can just save them or unload them > all, and that's it. > Currently I'm using it to load every resource in every package of my own. > It's not sutil, but I'm sure every view is updated this way. You can identify all view resources that reference a class like this: aClass := TextEdit. "for example" SessionManager current resourceManager allResourceIdentifiers select: [:each | each resource hiddenClassReferences includes: aClass] > If anyone is interested in this incipient tool, let me know and I'll just > send it. Good idea. Of course this suggests an obvious enhancement to the system, i.e. to identify and load resources that might be affected automatically before making any changes to the shape of classes, saving the resources again after the change. I think a confirmation prompt would be appropriate where resources are found. Also there is potential to render the resources unloadable, so it would have to be undoable as part of the composite class change. I don't know why we didn't think of it before! Thanks Blair |
Free forum by Nabble | Edit this page |