[Mono-dev] Environment.GetFolderPath() behaviour inconsistent with .NET

Gabe Mc madeonamac at gmail.com
Sat Aug 20 01:06:04 EDT 2011

Ok, I could just be talking complete crap here, so just keep that in
mind. I didn't see the start of this thread, but this commentary really
got me to thinking that you could solve this problem in a different way.

> If you knew me better, you would know that I detest the gratuitous
> breakage of APIs for the sake of cleaning up, at the expense of
> breaking people's software.   Evidence can be found on assorted
> mailing lists and interviews.   

I recognize the distaste for breaking APIs. I have a similar aversion to
causing down-stream disruptions. I also recognize, however, that some
disruptions are not only unfortunate, but also sometimes necessary. At
some point, a critical bug or planned obsolescence is going to appear
that affects people already on your platform, that has to be fixed
because it doesn't conform to what the developer works with on "the
other" platform. It seems like, in a position like this, it would be
better to see if one could leverage a tool to automate some of the hard
work of downstream maintenance.

> This is not one of those things that can easily be detected, so it
> introduces subtle errors, which might be impossible to diagnose.

Indeed, the only real way to check to see that downstream users will be
affected is to make sure one has a passing test that defines what the
current implementation _does_ and a failing test for what the
implementation _should_ do. However, once you have that knowledge, you
could easily begin to annotate methods and classes with information
about what will be breaking in this release. Indeed, I could see you
even attaching metadata to the test cases for pre- and post-iteration
notices, tying together these two tests to the method that is changing
or disappearing, all in annotations. 

You could then have a post-build step use the Cecil library to strip out
those annotations from the library (to remove bloat), and use the
information in them to generate a small library of information about
what changed (like NAME.VERSION.diff.dll). That new library could passed
on the command line to another tool that loads it, looks at the metadata
and looks at any and all of the other libraries it finds on the command
line, loads them, and checks to see if any of those libraries have
potential breakages associated.  

Now you have two happy downstream customers: the existing group that now
uses the output of this process, since this tool will tell them all of
the places that they should fix before they even hit F8 to rebuild to
see the errors; and, your new customers see that you have a consistent
record of tracking changes and notifying them of downstream breaks more
easily. Older users get to update their code, and new users get to to
bring their code to new platforms more easily. Everybody can then trust
but verify.

Since downstream users probably move platforms relatively slowly, they
could easily use this tool on the output of their builds (and even use
it on their own stuff!), to verify that they will not be breaking
anything in their next release for their internal clients!  Now, you
could give them a complete guide, all from the metadata, about how they
should upgrade their code. The best form of code communication!

> The only way this would be remotely responsible is to entirely rip out
> the API from the library, so every app that depended on it got a
> message "The method does not exist, replace with XXX".    

Now, all of the API changes could be noted easily at build time as
failing, so they can refactor until they are green. A tool like that
could be used by other people too. Lots of library writers with large
code bases could use it, I'm sure.

> Faced with ripping out the API, or keeping the behavior, I will side
> with "keep the behavior" and anyone that wants to get access to
> ~/Documents, will have to deal with this difference.   

Again, you'd be ripping out APIs, but maybe you spit out two dlls, one
to be used at compile time and another for runtime. That way they could
see in the report printout that they still have API calls that are
invalid, though it wouldn't technically fail the build, because that
code that is removed could still be present in the compile-time dll. Now
that I think about it, you could make it even cooler: say you have a
serries of these DLLs, you could create a tool to combine several
versions together into one patched compile-time DLL. If you're going
from something like 1.3 -> 1.7, as a downstream user, I wouldn't have to
apply 1.4.diff.dll, 1.5.diff.dll, 1.6.diff.dll, and 1.7.diff.dll.
Instead, the tool could combine multiple migrations into one file,
annotating which breakage comes from which release.

> People *porting* software already have to do a lot of work to port,
> this is something else that they will deal with.    People that
> trusted us with their code in the first place should not pay the
> price.

As I said, this would actually pretty well split the labor for porting
and maintaining software. All of the existing downstream users would be
made aware of potential breaks and how to fix them, and upstream users
can submit patches and reports about how the API should be fixed, so
that it can be compared to "the other" platform's behavior. Maybe even
run them both on a Windows build box, so that you can constantly see
whether the submitted patches actually conform to the submission. (Maybe
even use PEX for this, to inject behavior to see if the method calls
fail in the same way?)

> Feel free to fork Mono and maintain Mono on your own with your patch.

No thanks.

> Maybe history will prove you were right :-)
> Miguel

Unlikely. I like my solution better ;) 

Sorry if this was long and kind of rambling. I think about this kind of
stuff a lot, as a (somewhat) former build engineer. I think this kind of
stuff is pretty cool, and it was an interesting thought experiment I
thought I could write down. With a basic appraisal, it doesn't seem
_too_ outlandish that at least some minor functional bits could be done,
though some of the advanced functionality would, of course, require
significantly more work -- possibly much more than a neophyte to the
toolchain like myself could envision. Does anyone else think something
like this _could_ be done? Would there be any value in it?


;tldr: Scumbag developer has weird idea, foists it on people he's never
met, on a platform he's not an expert on, and asks for serious feedback.

More information about the Mono-devel-list mailing list