The Visual Basic EE has a similar origin story. From VS 2002 through VS 2008 it was a separate service from the Compiler and IDE. That meant language features had to be implemented three times.
The three services all shared parse trees and a portion of the bound nodes but that was it. The compiler and IDE shared their symbol import code as they read raw IL to produce symbols. The EE though used IDebugSymbolProvider docs.microsoft.com/en-us/dotnet/a…
The IDebugSymbol provider layer essentially exposed all of the information you needed from IL without exposing the raw IL. This meant though every time we changed IL or found a new piece of info we needed from IL it put pressure on the debugger team to tweak this layer to help us
Consider for example generics. Those came after the initial implementation of IDebugSymbolProvider. Hence part of the cost of generics was finding a way to expose all the information we needed. That is obviously a big one but there were lots of smaller issues of this nature
That meant implementing a language feature in the EE was very different than the compiler or IDE. Completely different symbol table to work on. Basically an entire new way of thinking about types to learn and digest.
Further complicating the problem is the IDE and EE code lived in the same DLL even though their respective services had different lifetimes (as well as they could load / unload in a variety of ways).
This would've been fine if the IDE and EE were well partitioned within the DLL. They were not though, they actually attempted to share a number of different services yet the IDE and EE had very different lifetimes and could be loaded / unloaded in virtually any order (tricky)
I got involved with this during VS 2008. The dev who used to own the EE left the team and I was asked to take over and fix up extension methods + implement a few features. At the time I worked on the compiler team and had a solid understanding of how the lang worked. Easy right?
Wrong. It ended up being pretty massive undertaking. The more complex features became the more expensive it was to replicate in the EE. Extension methods + dynamic ended up being so expensive it became a bit of a breaking point for us: decided that we needed to do better.
Started by reaching out to the C# team and they showed us all the progress they'd made in 2005 / 2008 by re-using the compiler code base in the EE and leveraging raw IL metadata reading. EE features were basically free for them.
The approached seemed like a dream from where we were at the time and we decided to take a similar approach. It was basically a full rewrite but the cost was estimated to be less than the time we'd spent on extension methods in the EE alone so we went for it.
The one difference we did is that we decided to treat the compiler as a service. Did some initial work to factor the compiler to a LIB that got linked into vbc as well as the EE. There were no #if that we leveraged in the EE anymore, compiler was an API.
That was actually a bit of a hard sell. #if was the way of life for the last ten years, why did we want to make it harder by thinking about APIs? Eventually though we persuaded the dev team and moved forward with the rewrite.
We also used the rewrite as a chance to fully separate the EE and IDE code bases by creating a new DLL: vbee.dll. That housed the EE only and allowed us to remove a lot of #if from the IDE code base too.
The work was completed for VS 2010. That EE implementation served us as the primary EE until Roslyn shipped. It still lives in VS under some legacy debugging options though.
It was the first major component that I ever designed + authored in VS and I remain extremely proud of the work. Even so I'm looking forward to the day we can fully remove it from the project as it still has some occasional maintenance cost to deal with.
• • •
Missing some Tweet in this thread? You can try to
force a refresh
One challenging aspect of managing large @github repos is dealing with issue backlogs. Every mature product has issues that fall into a gray area of "yes this is real, we'd accept a fix but it's so minor it will never really have enough priority for us to fix". Low pri issues.
Over time the count of such issues grows into the hundreds or thousands. Pretty soon you find that these issues are absolutely dominating your backlog. No one wants to open their repo and see 2,000+ open issues but what to do?
Closing these types of issues is not a great solution. That is a strong signal that you don't want a fix here which isn't the case. It's a real bug, it's just not going to meet the bar. It's also the type of issue that can be good "first issue" candidates for new contributors.
Wanted to share the steps I use when attempting to establish a coding style in a software project. Seen a number of people struggle with this over the years and wanted to share a strategy I've had some success with.
First gain consensus on the idea, **not** the implementation. Get developers to agree that a single style would be desirable. Push on ideas like it helps reduce friction on PRs, makes code more portable within your code base, easier for new developers to learn, etc ..
Nominate and choose a "decider". There will be conflict over style choices. Team needs to pick a member to make the final decision on style before the various styles are discussed. This helps the team pick someone who's decisions they respect, not because they share the same view
I think developers often lose sight of the fact that the C# type system is not the .NET type system. Instead the C# type system is merely a layer on top of the .NET type system providing both additional capabilities and additional restrictions.
Think most developers if asked would say C# is a super set of the .NET type system. Providing only new capabilities like lambdas, dynamic, pattern matching, etc ...
In reality though we also have restrictions that, while likely well meaning when initially implemented, are leaky abstractions that are pretty easy to poke through once you know the right levers to pull.