Refactoring is a term coined by Martin Fowler. It describes an action of changing
the structure of a code without altering it's behaviour.
We are performing refactorings daily in our jobs - we rename, move, change classes and methods. Those refactorings, however, are usually highly specific
to one's projects and will be performed only once.
However, there are three groups of refactorings which can be performed on
multiple projects without knowing their specifics:
- Adaptation to library API changes
- Language version or dialect update
- Language change (e.g. C# -> Java)
In this article we will focus on the first two types of refactoring. Both
of those refactoring types are absolutely independent of the project code itself.
When using a library, we are provided with a set of methods and classes to achieve the functionality of the library. If for some reason the developers of the library decide to change the API of the library, all the projects that are using this library will have to perform the same changes if they want to update the library version. In this case, the library can be both conventional library and a framework, as in essence they both only provide APIs.
Also, all of the projects will be written in some programming language. All the projects will use the same, strictly defined language constructs. And in the case of language evolution, all developers will be able to perform same abstract changes on their projects.
In these cases, wouldn't it be nice if someone wrote and shared all the changes necessary
and all others could automatically apply those changes on their projects? :)
Having done quite an extensive research in this field for my bachelor paper, I have made a prototype in C# which is supposed to migrate .NET projects, since there are no such tools for C# environment which I'm the most familiar with.
Now what do I mean by migration? Migration, both in my paper and in the tool, signifies a series of refactorings, which can be shared and executed across multiple projects.
Such migrations can be adaptations for library or framework API changes, language
version updates or any arbitrary other refactorings expressed through a change of AST (abstract syntax tree).
Everything can be written in one
.cs file, which can be versioned and shared across multiple projects! Moreover, it doesn't even need to be in any project!
If you happen to need higher level migrations, the tool provides fluent API -based migration builder, which can easily combine multiple prebuilt higher level migrations.
On the other hand, if you need something more specific, like changes for language migration, you are given the plain Microsoft's
SyntaxTree to work with as you need.
The tool and its detailed documentation can be found on:
A simple CLI tool to easily migrate .NET projects by writing custom migrations.
This tool is built with intention to create shareable migrations to be able to easily adapt to library, framework or even language updates.
- Rename class, interface, method, member, namespace
- Add, remove, change, reorder arguments
- Replace class, method
- Change method return type
Install the tool by using:
dotnet tool install -g refresh.tool
Use the tool:
refresh -p Path/To/Project.csproj -m Path/To/Migration.cs
Install Refresh.Components Nuget package in order to get Intelli-Sense support:
Migration.cs can be any C# class, implementing IMigration and it can have any name (Migration, MyMigration, CustomMigration etc.).
SyntaxTree Apply(SyntaxTree initialAST, MigrationContext context);
SyntaxTree is just
Microsoft.CodeAnalysis.SyntaxTree without any alterations. This is an AST of a…
Everyone is welcome to suggest improvements, report bugs, etc.!:)
If someone happens to be interested, please provide any feedback here in the comments or on the github repo! :)
Also, have you faced any breaking changes in the libraries that required a lot of manual refactoring? If so, I would love if someone shared it with me and I could see if I can adapt the tool to fit it. Maybe it will save someone a bit of time!