Multiple Solution Support

Although MS still think "Single Solution", it quite obvious that support for
multiple solutions is necessary.
Currently our project consists of about 30 solutions and when trying
refactor a feature such as a method
name, we have a problem. We can only perform the update on the current
solutions open.
Take for example a solution consisting the Infrastructure layer, changing an
interface needs to be reflected to all usages, without support for multiple
solutions, this task is impossible.
Any thoughts on that subject?
How about letting the user add solution targets manually to the setting
options?

thanks,

Jacob


19 comments
Comment actions Permalink

Jacob,

could you please describe in more details your scenario? What number of
projects are in each of your 30 solutions? How do you maintain
cross-solution dependencies among your projects?
Finally, why can't you put all your projects into the a single solution?

Sorry for curiosity, but as far as I understand it, a common practice in
VS.NET
is to join all related projects into a solution. Different projects may
represent different
architecture layers of the application. So having many solutions for an
application seems to
be a bit uncommon.

Thanks,
Dmitry

"Jacob Berezovsky" <jacobber@mail.ru> wrote in message
news:c5u1c8$jcu$1@is.intellij.net...

Although MS still think "Single Solution", it quite obvious that support

for

multiple solutions is necessary.
Currently our project consists of about 30 solutions and when trying
refactor a feature such as a method
name, we have a problem. We can only perform the update on the current
solutions open.
Take for example a solution consisting the Infrastructure layer, changing

an

interface needs to be reflected to all usages, without support for

multiple

solutions, this task is impossible.
Any thoughts on that subject?
How about letting the user add solution targets manually to the setting
options?

>

thanks,

>

Jacob

>
>


0
Comment actions Permalink

Actually, this is very common case. This is when you have projects that are common libraries, and there can be several of them. For example, I have "Common", "Controls" and "Services" assemblies that are shared across MANY projects. You probably have the same case - JetBrainsShared.dll might be used in several projects. So when you refactor such a shared lib (which is not public, i.e. no legacy issues here) you want all usages to be refactored as well. However, this is not what Re#er should do. This is more to Configuration Management, than to development.

Nevertheless, Re#er could help. If it were possible to (optionally) save refactorings in the project and replay them in different solution. I don't have specific "how-to" off my head now, but if Re#er were logging all non-local refactorings (i.e. visible from outside of assembly), timestamping them and warning if some (dependant) project in opened solution misses changes and giving option to apply... Well, I think the whole world will give many thanks to you :)

0
Comment actions Permalink

Ilya,

thanks for your opinion.

I suppose the necessity to modify shared assemblies does not rise very
often. Provided this,
wouldn't it be an option for you to create a temporary solution that
contains all the projects from
solutions in question and perform refactoring in this solution?

"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:27019263.1082373887427.JavaMail.javamailuser@localhost...

Actually, this is very common case. This is when you have projects that

are common libraries, and there can be several of them. For example, I have
"Common", "Controls" and "Services" assemblies that are shared across MANY
projects. You probably have the same case - JetBrainsShared.dll might be
used in several projects. So when you refactor such a shared lib (which is
not public, i.e. no legacy issues here) you want all usages to be refactored
as well. However, this is not what Re#er should do. This is more to
Configuration Management, than to development.
>

Nevertheless, Re#er could help. If it were possible to (optionally) save

refactorings in the project and replay them in different solution. I don't
have specific "how-to" off my head now, but if Re#er were logging all
non-local refactorings (i.e. visible from outside of assembly), timestamping
them and warning if some (dependant) project in opened solution misses
changes and giving option to apply... Well, I think the whole world will
give many thanks to you :)


0
Comment actions Permalink

A year ago an option to create MegaSolution that contains all projects and common assemblies just to refactor a method in WebLoader class would be feasible. Now it is not. I have 356 .csproj files, from which 113 uses just one of my shared libraries, "Common.csproj".

Do you think it is REALLY possible to create such a MegaSolution without having VS.NET crashed? :) Anyway, it will take forever to perform the refactoring, not to say how long it will be loading into VS.NET...

However, many of those projects are rarely used at all. What I was thinking of was "Refactory On Demand". When I work on some current project and need a change to shared assembly, I just perform the change and feel happy. When I open another solution with different project, that doesn't have this change applied, I have an option to perform the "delayed refactory"... Also note, that many refactorings doesn't need to be logged - only breaking changes, such as renames and signature changes. And more, "breaking" change should be considered on source code level vs. binary level, which is much simpler.

Well, it was just an idea, a good feature to have, but not required.

0
Comment actions Permalink

Well, if you have so huge amount of code that it is not feasible to put all
it into a solution,
let's consider another option. Assume you have a project P that is shared
among solutions S1 and S2,
and you need to change something from the interface of P. Then you can
proceed as follows:

1) Load solution S1 with its copy of P and make the change in this solution
2) Load solution S2 with original (not changed) copy of P and make the
change there

In this way, you'll update all usages in the shared code twice, but if you
have made the same change in
both solutions, this should not be a problem.

It differs with your solution in that you need to have the original code of
the shared project and perform the refactoring twice.
However, it does not involve any logging and therefore seems to be much
simpler and requires no additional support on
the tool's side. Though your proposal is perhaps easier to use...

"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:32578285.1082376770501.JavaMail.javamailuser@localhost...

A year ago an option to create MegaSolution that contains all projects and

common assemblies just to refactor a method in WebLoader class would be
feasible. Now it is not. I have 356 .csproj files, from which 113 uses just
one of my shared libraries, "Common.csproj".
>

Do you think it is REALLY possible to create such a MegaSolution without

having VS.NET crashed? :) Anyway, it will take forever to perform the
refactoring, not to say how long it will be loading into VS.NET...
>

However, many of those projects are rarely used at all. What I was

thinking of was "Refactory On Demand". When I work on some current project
and need a change to shared assembly, I just perform the change and feel
happy. When I open another solution with different project, that doesn't
have this change applied, I have an option to perform the "delayed
refactory"... Also note, that many refactorings doesn't need to be logged -
only breaking changes, such as renames and signature changes. And more,
"breaking" change should be considered on source code level vs. binary
level, which is much simpler.
>

Well, it was just an idea, a good feature to have, but not required.



0
Comment actions Permalink

I would have to agree with Ilya. Maintaining a "Mega Solution" is not a good
option for a number of reasons.
The first, dealing with assembly references that are different ( project
refs & dll refs ),
second, the larger the solution, the longer it takes to load, third, I would
put my money on the .Net Studio performance when it comes to dealing with
such large scale solutions.
Our project contains about 50 solutions and hundreds of projects divided
between a number of teams.
I think that refactoring on-demand is an option but it could be extremely
difficult to implement.
A simpler approach would be to configure the ReSharper DB manually by adding
the projects and their path or
a concept similar to the Java class path.
I would go with the project path option.
I think it could be very easy to implement and I can say from my part, a
very significant feature of the ReSharper support for refactoring.
I think that every large scale project would benefit from this feature.

cheers,

Jacob


0
Comment actions Permalink

Why do I need to keep so many copies of code locally when I have code repository (CVS)? This would add burden to an updating from CVS (I have to update all copies), on keeping them in sync and so on... Also, as I said several projects are really touched, so I will notice that "dupe refactory" is needed too late to remember what has changed... No, this is not an option.

I understand the difficulty of the proposed feature, I just think about an easy way to cover most significant use cases.

0
Comment actions Permalink

I don't think it is easier to maintain code in sync utilizing "code path" approach. It needs to reparse the whole dependant project at the moment of refactoring to avoid Re#er from eating too much resources when the shared project is not changed. Also, I don't know if Re#er uses VS.NET DOM and thus is dependant of the fact that project should be loaded into IDE to process it.

Another level of complexity is added through the derived classes. Consider the class MyCommon defined in shared library, and public MethodOne in it is get renamed to MethodTwo. In different project (not in current solution), someone derives from MyCommon class to produce MySpecific. Thus, MySpecific's signature get changed indirectly and usages of MySpecific in other assemblies and projects should be fixed as well. This drives the system to extremely complex structure of tracking dependencies.

It also suffers from usability point of view - you blindly apply changes to side-stored code, without undo/redo opportunity, without checking if it compiles, and so on.

0
Comment actions Permalink


"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:14436156.1082383080445.JavaMail.javamailuser@localhost...

I don't think it is easier to maintain code in sync utilizing "code path"

approach. It needs to reparse the whole dependant project at the moment of
refactoring to avoid Re#er from eating too much resources when the shared
project is not changed. Also, I don't know if Re#er uses VS.NET DOM and thus
is dependant of the fact that project should be loaded into IDE to process
it.

ReSharper does not depend on the VS.NET Code Model. However, being an
add-in, it of course uses solution structure from VS.NET.


0
Comment actions Permalink

So can you estimate or just comment on the following scheme:

- project database may contain a history of refactorings.
- it is an option of the user to enable history tracking for each particular project
- only those edits that change existing public interface of the class are stored in history. E.g rename of the method parameter doesn't count, but changing return type does.
- history item contains enough information to perform single refactory as if it was performed with project loaded. That is, changing type name and then changing method name in this class will have two entries, but one cannot perform second one alone - type doesn't exist. The result of this rule is simplicity, and restriction to perform all or none pending requirements in order.
- each history item is assigned unique item number, scoped in project.
- when solution is opened, each project reference (skip raw assembly reference) of each project is checked if it contains latest refactorings.
- if project needs changes, user is prompted and changes applied using history items.
- user has an option to clear history for project
- history should be text (XML?) data, so it can be stored in code repository.

This doesn't sound very complex to me. I suppose, Re#er uses some sort of "verbs" or "commands" internally and something like Visitor pattern, so this is a matter of serializing object of something like IRefactoringAction...

0
Comment actions Permalink

Ilya,

I think this scheme (being coupled with a repository that supports
versioning) generally sounds reasonable for
really large solutions in which different projects are used with different
frequencies. However, it seems for me
that the same effect can be achieved by using local version control system
(LVCS) just like IDEA offers. Briefly,
LVCS maintains a log similar to what you propose and provides an option to
rollback to a specific version.

Given that LVCS is maintained on per-project basis, all you need when you
open a solution that contains the
just-has-been-refactored shared project, is to rollback changes in that
project, and run the same refactored you've
performed in another solution. While it still requires more action from you,
it does not introduce the notion of
'pending refactorings' that seems to be relatively complex to me.

What do you think?

"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:29526349.1082385107355.JavaMail.javamailuser@localhost...

So can you estimate or just comment on the following scheme:

>

- project database may contain a history of refactorings.
- it is an option of the user to enable history tracking for each

particular project

- only those edits that change existing public interface of the class are

stored in history. E.g rename of the method parameter doesn't count, but
changing return type does.

- history item contains enough information to perform single refactory as

if it was performed with project loaded. That is, changing type name and
then changing method name in this class will have two entries, but one
cannot perform second one alone - type doesn't exist. The result of this
rule is simplicity, and restriction to perform all or none pending
requirements in order.

- each history item is assigned unique item number, scoped in project.
- when solution is opened, each project reference (skip raw assembly

reference) of each project is checked if it contains latest refactorings.

- if project needs changes, user is prompted and changes applied using

history items.

- user has an option to clear history for project
- history should be text (XML?) data, so it can be stored in code

repository.
>

This doesn't sound very complex to me. I suppose, Re#er uses some sort of

"verbs" or "commands" internally and something like Visitor pattern, so this
is a matter of serializing object of something like IRefactoringAction...


0
Comment actions Permalink

Given that LVCS is maintained on per-project basis,
all you need when you
open a solution that contains the
*just-has-been-refactored *shared project,


Bolded one is the key misunderstanding here. I will not probably open some project for relatively long time. And when I open it, I don't have any idea of what those refactorings were. I will have to store somewhare version number of shared project, with which current one was compiled last, then get a diff of current and that version, and then guess, what where those refactorings.

does not introduce the notion of
'pending refactorings' that seems to be relatively
complex to me.


For me the main complexity of this feature is that code is not necessary edited with "refactoring actions". You obviously cannot log all changes to shared lib, and thus "delayed" refactorings can be rendered obsolete, incorrect or whatever. That's the show stopper, really. However, the idea itself is great for large systems, with many solutions and projects. We need to think about it further some day.

What do you think?

I think you may want to put it in the "think-about-it-in-the-future" list :)

0
Comment actions Permalink


"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:28127002.1082390704157.JavaMail.javamailuser@localhost...

Given that LVCS is maintained on per-project basis,
all you need when you
open a solution that contains the
*just-has-been-refactored *shared project,

>

Bolded one is the key misunderstanding here. I will not probably open some

project for relatively long time. And when I open it, I don't have any idea
of what those refactorings were. I will have to store somewhare version
number of shared project, with which current one was compiled last, then get
a diff of current and that version, and then guess, what where those
refactorings.

Well, now I see it... My error was that I forgot about a possibility to not
open some projects for a long time, and then return to them. In such case,
we of course need to store the version number of the shared project
somewhere so that to be able to recover the correct version that was actual
at that time
the rarely used project was last built. I believe we must think about
supporting such scenario in the future.

Thanks for very interesting thread & ideas. It really opened my eyes on some
things. In particular, it was surprise for me to know that someone has
already such a
great amount of C# code.

Thanks,
Dmitry


0
Comment actions Permalink

Hmm, just thought. What if we could identify just the timestamp of the succesfull compilation of the project and last time project updated? Here is an example to clarify the idea:

Solution: SharedLibs
- Project: Common
-- Last modified: 16 Apr 2004.
-- Last successful build: 17 Apr 2004
- Project: Services
-- Last modified: 17 Apr 2004
-- Last successful build: 17 Apr 2004

That is, solution SharedLibs was updated and built on 17 Apr 2004.

Solution MyProject:
- Project: MyProject
-- Last modified: 10 Mar 2004
-- Last successful build: 10 Mar 2004
-- Reference: Project Common

That is, MyProject has been compiled against Common.dll on 10 Mar 2004 and project has been changed since.

If one could access this information when on 18 Apr 2004 MyProject won't compile, he can easily check diffs between version as of 10 Mar and today, then determine what the changes were. I cannot recall where in VS.NET one see such data, probably nowhere.

Hey, another idea :) Why not be able to get just a string representaion of the refactory action? Like, "RenameType(MyCompany.MyProduct.MyType, MyMnemonicTypeName)" and then be able to replay the action from something like a command window? If this were possible, I would be able to store this command in comments for the commit (or, check-in) and retrieve it through history of my favorite version control system, or simple text file in the project? You even can automatically maintain this history file, but no automatic replay necessary. One can check what refactorings were made, decide which are needed and just replay them manually!

0
Comment actions Permalink


"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:15905290.1082393276383.JavaMail.javamailuser@localhost...

Hmm, just thought. What if we could identify just the timestamp of the

succesfull compilation of the project and last time project updated? Here is
an example to clarify the idea:
>

Hey, another idea :) Why not be able to get just a string representaion of

the refactory action? Like, "RenameType(MyCompany.MyProduct.MyType,
MyMnemonicTypeName)" and > > then be able to replay the action from
something like a command window? If this were possible, I would be able to
store this command in comments for the commit (or, check-in) and > >
retrieve it through history of my favorite version control system, or simple
text file in the project? You even can automatically maintain this history
file, but no automatic replay necessary. > One can check what refactorings
were made, decide which are needed and just replay them manually!

In fact, IDEA has 'migrate' feature that allows to externalize refactorings
into a file and replay them by applying this file to another project later.


0
Comment actions Permalink

I'm not familiar with IDEA, I didn't develop in Java since 1.0. But... What is the problem then? :)) You already done it, I'm pretty sure the model of Re#er addin is very close to that one in IDEA (why would one reinvent the wheel?), what is the reason that stops you from implementing this thing in Re#er?

0
Comment actions Permalink

Ilya,

Decided to put mu 2 cents here, though I was afraid to run into such an
active discussion.

My vision follows:

1) IDEA's migrate feature initially intended to memorize some
refactoring batches to keep API clients up-to-date. One could create a
batch, save it to file and then distribute it with new version of the
library to cliens using IDEA. This is not so good in the case because
changing API from version to version a way which doesn't keep backward
compatibility isn't a good practice. Even with this feature this makes
non-IDEA users deal with such changes themselves.
2) However, for local projects it's more than acceptable
3) ReSharper really have an option not only to record batch to a file,
but to attach the information to the project (with automatically putting it
to VCS). This way when one opens a project which references another project
having such batch attached ReSharper could propose to execute the batch.
4) There are some implementation difficulties, however, so I can't say
when this feature gets implemented.

--
Oleg Stepanov
Software Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:13140363.1082394317990.JavaMail.javamailuser@localhost...

I'm not familiar with IDEA, I didn't develop in Java since 1.0. But...

What is the problem then? :)) You already done it, I'm pretty sure the model
of Re#er addin is very close to that one in IDEA (why would one reinvent the
wheel?), what is the reason that stops you from implementing this thing in
Re#er?


0
Comment actions Permalink

Does this mean, that feature will be planned? I understand that it can be not available until later in the development cycle, but if the answer is "yes" it will have major consequnces for me. I will simply stop searching for other tools for a while :) And continue to give my feedback to this product. I'm very much concerned about team productivity. Any team-oriented feature in re#er will give it definite bonus over other tools. Large scale solutions is another thing to support, but this will take a while to think out. I will share some ideas later this week. If you need them, of course.

0
Comment actions Permalink

Ilya,

The only thing I can say now is that this feature is not planned for
1.0. It will probably implemented in 2.0, but only probably.

--
Oleg Stepanov
Software Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
"Ilya Ryzhenkov" <no_mail@jetbrains.com> wrote in message
news:9033861.1082468346027.JavaMail.javamailuser@localhost...

Does this mean, that feature will be planned? I understand that it can be

not available until later in the development cycle, but if the answer is
"yes" it will have major consequnces for me. I will simply stop searching
for other tools for a while :) And continue to give my feedback to this
product. I'm very much concerned about team productivity. Any team-oriented
feature in re#er will give it definite bonus over other tools. Large scale
solutions is another thing to support, but this will take a while to think
out. I will share some ideas later this week. If you need them, of course.


0

Please sign in to leave a comment.