What’s the big deal with folders?

If you’re a seasoned VBA developer, you probably have your “VBA Toolbox” – a set of classes that you systematically include in pretty much every single new VBA project.

Before you’ve even written a single line of code, your project might look something like this already:

ProjectExplorer

The VBE’s Project Explorer gives you folders that regroup components by component type: forms in a folder, standard modules in another, and classes in another.

That’s great ok for small projects, perhaps. But as your toolbox grows, the classes that are specific to your project get drowned in a sea of class modules, and if you’re into object-oriented programming, you soon end up finding needles in a haystack. “But they’re sorted alphabetically, it’s not that bad!” – sure. And then you come up with all kinds of prefixes and naming schemes to keep related things together, to trick the sorting and actually manage to find things in a decent manner.

The truth is, this sucks.

Now picture this:

You shouldn’t have to care about a component’s type. Since forever, the VBE has forced VBA developers to accept that it could possibly make sense to have completely unrelated forms grouped together, and completely unrelated classes together, just because they’re the same type of VBA objects.

But it doesn’t have to be this way. I like how Visual Studio /.net lets you organize things in folders, which [can] define namespaces, which are a scope on their own.

There’s not really a concept of namespaces inside a VBA project: you could simulate them with standard modules that expose global objects that regroup functionality, but still every component in a project is accessible from anywhere in that project anyway. And who needs namespaces anyway?

Rubberduck 2.0 will not give you namespaces – that would be defying the VBA compiler (you can’t have two classes with the same name in the same project). What it will give you though, is folders.

Cool! How does it work?

Since the early versions of Rubberduck, we’ve been using @annotations (aka “magic comments”) in the unit testing feature, to identify test modules and test methods. Rubberduck 2.0 simply expands on this, so you can annotate a module like this:

'@Folder Foo.Bar

And that module will be shown under a “Bar” folder, itself under a “Foo” folder. How simple is that! We’ll eventually make the delimiter configurable too, so if you prefer this:

'@Folder Foo/Bar

Then you can have it!

With the ability to easily organize your modules into a “virtual folder hierarchy”, adhering to the Single Responsibility Principle and writing object-oriented code that implies many small specialized classes, is no longer going to clutter up your IDE… now be kind, give your colleagues a link to Rubberduck’s website 😉


The Code Explorer

The goal behind the Code Explorer feature, is to make it easier to navigate your VBA project. It’s not just about organizing your code with folders: since version 1.21, the Code Explorer has allowed VBA devs to drill down and explore a module’s members without even looking at the code:

CodeExplorer-expanded

The 2.0 Code Explorer is still under development – but it’s coming along nicely. If you’re using the latest release (v1.4.3), you’ll notice that this treeview has something different: next release every dockable toolwindow will be an embedded WPF/XAML user control, which means better layouts, and an altogether nicer-looking UI. This change isn’t being done just because it’s prettier: it was pretty much required, due to massive architectural changes.

Stay tuned!

OOP in VBA?

VBA is an Object-Oriented language…

…whether we agree or not.

Object-Oriented Programming (OOP) is really all about 4 little things:

  • Abstraction.
  • Encapsulation.
  • Polymorphism.
  • Inheritance.

To make things clear: there’s no inheritance in VBA. But it doesn’t matter, because we can easily compensate with composition, which is often a better design decision, even in languages that support class inheritance.

The key to OOP, is classes. Why? Because classes are a blueprint for objects, …which are kinda the whole point of OOP.


 

Abstraction

If you’ve been writing code, you’ve been making abstractions. A procedure is abstracting a series of executable operations; a module abstracts a group of related operations, even variables are an abstraction, abstracting the result of an operation.

Or is that too abstract?

Levels of abstraction

If you think of the steps required to, say, make coffee, you might think of something like this:

  • Make sure there’s water in the coffee maker
  • Make sure there’s coffee in the coffee maker
  • Start the coffee maker

That would certainly make coffee, right?

What sub-steps could there be to make sure there’s water in the coffee maker? And to make sure there’s coffee in the coffee maker? Or even to start the coffee maker? These sub-steps are at a lower level of abstraction than the 3 higher-level ones.

Clean code operates on a single level of abstraction, and calls into more and more specialized code: notice we don’t care where the water compartment is at the higher levels.

That’s why we put the public members at the top: because they’re at a higher level of abstraction than the private members they’re calling.

Classes are an important abstraction: they define objects, which encapsulate data and expose methods to operate on it.


Encapsulation

Similar to abstraction, encapsulation abstracts away implementation details, exposing only what other code needs to work with.

Global variables are pretty much the opposite of encapsulation; and if you have a public field in a class module, you’re not encapsulating your data.

Instead of exposing a field, you’ll be exposing properties. Property accessors can have logic in them, and that’s the beauty of encapsulation: you’re keeping a value to yourself, and telling the rest of the world only what it needs to know.


Polymorphism

If you’ve never worked with interfaces before, that one can be hard to grasp… but it’s the coolest thing to do in VBA, because it truly unlocks the OOP-ness of the language.

Once, I implemented IRepository and IUnitOfWork interfaces in VBA. These interfaces allowed me to run my code using “fake” repositories and a “mock” unit of work, so I was able to develop a little CRUD application in Excel VBA, and test every single bit of functionality, without ever actually connecting to a database.

That worked, because I wrote the code specifically to depend on abstractions – an interface is a wonderful abstraction. The code needed something that had the CRUD methods needed to operate on the database tables: it didn’t care whether that thing used table A or table B – that’s an implementation detail!

The ability of an object to take many forms, is called polymorphism. When code works against an IRepository object rather than a CustomerRepository, it doesn’t matter that the concrete implementation is actually a ProductRepository or a CollectionBasedTestRepository.


Inheritance

VBA doens’t have that, which is sometimes frustrating: the ability for a class to inherit members from another class – when two classes relate to each other in an “is-a” manner, inheritance is at play.

Yes, inheritance is one of the 4 pillars of OOP, and composition isn’t. But inheritance has its pros and cons, and in many situations composition has more pros than cons. Well, class inheritance at least, but in VBA class and interface inheritance would be intertwined anyway, because a VBA interface is nothing more than a class with empty members.


What of Composition?

In VBA instead of saying that a class “is-a” something, we’ll say that the class “has-a” something. Subtle, but important difference: most languages that do support inheritance only ever allow a given type to inherit from one, single class.

When an object encapsulates instances of other objects, it’s leveraging composition. If you want, you can expose each member of the encapsulated object, and completely simulate class inheritance.


Ok…

…So, what does that have to do with Rubberduck?

Everything. The Visual Basic Editor (VBE) isn’t really helping you to write Object-Oriented code. In fact, it’s almost encouraging you not to.

Think of it:

The only way to find an identifier in a project is to make a text search and iterate the results one by one, including the false results.

The more classes and modules you have, the harder organizing your project becomes. And when you realize you need some sort of naming scheme to more efficiently find something in the alphabetically-sorted Project Explorer, it’s too late to rename anything without breaking everything.

So people minimized the number of modules in their VBA projects, and wrote procedural code that can’t quite be tested because of the tight coupling and low cohesion.

Tested?

I don’t mean F5-debug “tested”; I mean automated tests that run a function 15 times with different input, tests that execute every line of application logic without popping a UI, hitting a database or the file system; tests that test one thing, tests that document what the code is supposed to be doing, tests that fail when the code changes and breaks existing functionality you thought was totally unrelated.


Rubberduck loves OOP

It was already the case when the current v1.4.3 release was published, and the upcoming v2.0 release is going to confirm it: Rubberduck is a tool that helps you refactor legacy VBA code to OOP, and helps you write testable – and tested – object-oriented VBA code.

The Find implementations feature is but an example of a wonderful object-oriented navigation tool: it locates and lets you browse all classes that implement a given interface. Or all members, wherever they are, that implement a given interface member.

Is OOP overkill for VBA? Sometimes. Depends what you need VBA for. But the IDE shouldn’t be what makes you second-guess whether it’s a good idea to push a language as far as it can go.

Breaking Changes – Part 2: Rubberduck Menus

RUBBERDUCK 2.0 FLIPS EVERYTHING AROUND.

When numbering versions, incrementing the “major” digit is reserved for breaking changes – and that’s exactly what Rubberduck 2.0 will introduce.

I have these changes in my own personal fork at the moment, not yet PR’d into the main repository.. but as more and more people fork the main repo I feel a need to go over some of the changes that are about to happen to the code base.

If you’re wondering, it’s becoming clearer now, that Rubberduck 2.0 will not be released until another couple of months – at this rate we’re looking at something like the end of winter 2016… but it’s going to be worth the wait.


Inversion of Control

In Rubberduck 1.x we had a class called RubberduckMenu, which was responsible for creating the add-in’s menu items. Then we had a RefactorMenu class, which was in theory responsible for creating the Refactor sub-menu under the main Rubberduck menu and in the code pane context menu. As more and more features were added, these classes became cluttered with more and more responsibilities, and it became clear that we needed a more maintainable way of implementing this, in a way that wouldn’t require us to modify a menu class whenever we needed to add a functionality.

In the Rubberduck 2.0 code base, RubberduckMenu and RefactorMenu (and every other “Menu” class) is deprecated, and all the per-functionality code is being moved into dedicated “Command” classes. For now everything is living in the Rubberduck.UI.Command namespace – we’ll eventually clean that up, but the beauty here is that adding a new menu item amounts to simply implementing the new functionality; take the TestExplorerCommand for example:

public class TestExplorerCommand : CommandBase
{
    private readonly IPresenter _presenter;
    public TestExplorerCommand(IPresenter presenter)
    {
        _presenter = presenter;
    }

    public override void Execute(object parameter)
    {
        _presenter.Show();
    }
}

Really, that’s all there is to it. The “Test Explorer” menu item is even simpler:

public class TestExplorerCommandMenuItem : CommandMenuItemBase
{
    public TestExplorerCommandMenuItem(ICommand command)
        : base(command)
    {
    }

    public override string Key { get { return "TestMenu_TextExplorer"; }}
    public override int DisplayOrder { get { return (int)UnitTestingMenuItemDisplayOrder.TestExplorer; } }
}

The IoC container (Ninject) knows to inject a TestExplorerCommand for this ICommand constructor parameter, merely by a naming convention (and a bit of reflection magic); the Key property is used for fetching the localized resource – this means Rubberduck 2.0 will no longer need to re-construct the entire application when the user changes the display language in the options dialog: we simply call the parent menu’s Localize method, and all captions get updated to the selected language. …and modifying the display order of menu items is now as trivial as changing the order of enum members:

public enum UnitTestingMenuItemDisplayOrder
{
    TestExplorer,
    RunAllTests,
    AddTestModule,
    AddTestMethod,
    AddTestMethodExpectedError
}

The “downside” is that the code that initializes all the menu items has been moved to a dedicated Ninject module (CommandbarsModule), and relies quite heavily on reflection and naming conventions… which can make things appear “automagic” to someone new to the code base or unfamiliar with Dependency Injection. For example, ICommand is automatically bound to FooCommand when it is requested in the constructor of FooCommandMenuItem, and we now have dedicated methods for setting up which IMenuItem objects appear under each “parent menu”:

private IMenuItem GetRefactoringsParentMenu()
{
    var items = new IMenuItem[]
    {
        _kernel.Get<RefactorRenameCommandMenuItem>(),
        _kernel.Get<RefactorExtractMethodCommandMenuItem>(),
        _kernel.Get<RefactorReorderParametersCommandMenuItem>(),
        _kernel.Get<RefactorRemoveParametersCommandMenuItem>(),
    };
    return new RefactoringsParentMenu(items);
}

The end result, is that instead of creating menus in the VBE’s commandbars and handling their click events in the same place, we’ve now completely split a number of responsibilities into different types, so that the App class can now be injected with a very clean AppMenu object:

public class AppMenu : IAppMenu
{
    private readonly IEnumerable<IParentMenuItem> _menus;

    public AppMenu(IEnumerable<IParentMenuItem> menus)
    {
        _menus = menus;
    }

    public void Initialize()
    {
        foreach (var menu in _menus)
        {
            menu.Initialize();
        }
    }

    public void EvaluateCanExecute(RubberduckParserState state)
    {
        foreach (var menu in _menus)
        {
            menu.EvaluateCanExecute(state);
        }
    }

    public void Localize()
    {
        foreach (var menu in _menus)
        {
            menu.Localize();
        }
    }
}

These changes, as welcome as they are, have basically broken the entire application… for the Greater Good. Rubberduck 2.0 will be unspeakably easier to maintain and extend.

To be continued…

Breaking Changes – Part 1: Parser

Rubberduck 2.0 flips everything around.

When numbering versions, incrementing the “major” digit is reserved for breaking changes – and that’s exactly what Rubberduck 2.0 will introduce.

I have these changes in my own personal fork at the moment, not yet PR’d into the main repository.. but as more and more people fork the main repo I feel a need to go over some of the changes that are about to happen to the code base.

If you’re wondering, it’s becoming clearer now, that Rubberduck 2.0 will not be released until another couple of months – at this rate we’re looking at something like the end of winter 2016… but it’s going to be worth the wait.


 

Parser State

Parsing in Rubberduck 1.x was relatively simple:

  • User clicks on a command that requires a fresh parse tree;
  • Parser knows which modules have been modified since the last parse, so only the modified modules are processed by the ANTLR parser;
  • Once we have a parse tree and a set of Declaration objects for everything (modules, procedures, variables, etc.), we resolve the identifier usages we encounter as we walk the parse tree again, to one of these declarations;
  • Once identifier resolution is completed, the command can run.

The parse results were cached, so that if the Code Explorer processed the entire code base to show up, and then the user wanted to run code inspections or one of the refactor commands, they could be reused as long as none of the modules were modified.

Parsing in Rubberduck 2.0 flips this around and completely centralizes the parser state, which means the commands that require a fresh parse tree can be disabled until a fresh parse tree is available.

We’ve implemented a key hook that tells the parser whenever the user has pressed a key that’s changed the content of the active code pane. When the 2.0 parser receives this message, it cancels the parse task (wherever it’s at) for that module, and starts it over; anytime there’s a “ready” parse tree for all modules, the expensive identifier resolution step begins in the background – and once that step completes, the parser sends a message to whoever is listening, essentially saying “If you ever need to analyze some code, I have everything you need right here”.

Sounds great! So… What does it mean?

It means the Code Explorer and Find Symbol features no longer need to trigger a parse, and no longer need to even wait for identifier resolution to complete before they can do their thing.

It means no feature ever needs to trigger a parse anymore, and Rubberduck will be able to disable the relevant menu commands until parser state is ready to handle what you want to do, like refactor/rename, find all references or go to implementation.

It means despite the VBE not having a status bar, we can (read: will) use a command bar to display the current parser state in real-time (as you type!), and let you click that parser state command button to expand the parser/resolver progress and see exactly what little ducky’s working on in the background.


To be continued…

VariableNotUsedInspection: the false positives of v1.4, upcoming fixes of v2.0

One of my favorite features since we started working on this project, is the Code Inspections.

rd-code-inspections

I like it because, well, it does find things.

The problem is that, sometimes, under specific circumstances, it makes false claims. Take this code for example:

Public Sub FormatChart(cht As ChartObject)
    Dim ax As Axis
    Set ax = cht.Axes(xlValue)
    ax.MajorGridlines.Border.Color = RGB(200, 200, 200)
    ax.MinorGridlines.Border.Color = RGB(230, 230, 230)
    ax.Crosses = xlAxisCrossesMinimum
End Sub

Here Rubberduck 1.4.3 would say “Variable ‘ax’ is never used” – and suggest a quick-fix to remove the supposedly unused declaration. A quick-fix which, of course, would break the code. Is there a bug in the VariableNotUsedInspection code?

Believe it or not, there isn’t. What makes the inspection fire up false positives, is a bug in the identifier reference resolver that causes member calls to ignore the “parent” reference.

Another common case, is caused by – again – the resolver treating For and For Each loops as assignments, but not as usages. So in code like this:

 Dim fYear As Integer
 Dim fQuarterOfYear As Integer
 Dim fMonthOfQuarter As Integer
 Dim fWeekOfMonth As Integer
 Dim fDayOfWeek As Integer
 
 For fYear = fStartYear To fStartYear + years - 1
     Set current = FiscalCalendarDate.Create(currentDate, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, fYear, vbNullString)
 
     For fQuarterOfYear = 1 To 4
 
         current.FiscalDayOfQuarter = 1
         current.FiscalWeekOfQuarter = 1
         current.FiscalMonthOfQuarter = 1
 
         For fMonthOfQuarter = 1 To 3
 
             current.FiscalDayOfMonth = 1
             current.FiscalWeekOfMonth = 1
 
             If IIf(IsLeapYear(current.calendarYear) And current.FiscalMonthOfYear = 12, True, fMonthOfQuarter Mod 2 = 0) Then
 
                 For fWeekOfMonth = 1 To 5
 ...

You get a “Variable ‘fWeekOfMonth’ is not used” and “Variable ‘fQuarterOfYear’ is not used”, because the only place they’re ever used is in For loops.

Then you have the forgotten edge cases:

Private WithEvents indicator As ProgressIndicator

WithEvents variables are likely to be assigned a reference, but not necessarily to be themselves referenced anywhere. And if they aren’t, well then, they’re reported as “never used”. Which is a problem, because you don’t want a quick-fix to go and delete the WithEvents declaration that provides all these events you’re handling. So we’re going to be ignoring WithEvents variables.


Okay… Got any Good news?

Totally. Ducky 2.0 code inspections are being completely revamped. And all these false positives are being addressed, which means…

…most inspections will support “Fix all” options. Of course one shouldn’t “fix all occurrences in project” without actually reviewing the inspection results. But so far, it’s looking very, very good. This UI is still preliminary: we’re happy to hear (and integrate) your feedback!

Blue Print of 2.x

The foundation of the project needed a bit of clean-up and restructuring. The Big Refactoring is now pretty much completed, and with it, summer 2015’s feature freeze:

Feature-freeze until this is completed. We need to implement proper DI/IoC and make the code testable, if not tested. No ifs, no buts.

So we’re ready to start implementing the new features of 2.0. But before, we need to reconnect the pieces, by moving code from the 1.x “RubberduckMenu” and “RefactorMenu” classes, and into these “ICommand” implementations.


 

So, What’s Cooking?

Tons. The new architecture allows us to write code that is aware of the host application. This means Unit Testing commands can be disabled when the host is Outlook, for example (it seems executing VBA code on-demand from a VBE add-in isn’t possible in Outlook – ideas welcome). It also means we can write code inspections that warn about implicit references to Application.ActiveWorkbook in Excel, but that don’t run when the host application is Access, Word, or PowerPoint. Things like that, and…

Regex Search & Replace is coming. We’ll need a way to hijack Ctrl+F and Ctrl+H!

Smart Indenter is coming. The owners of this awesome add-in have graciously offered their source code to the Rubberduck project a while ago already; 2.0 isn’t releasing without an embedded Smart Indenter!

More grammar fixes on the way. This means fewer parser errors, more accurate inspections, navigation and refactorings, i.e. a more reliable tool.

Source Control Integration continues to improve, and early minor releases of 2.x will likely see a new WPF/XAML UI.

More translations have been completed since the last release: 2.0 will speak English, French, Swedish, German, Japanese… and every other translation we receive a PR for in the next.. uh… …6-8 weeks.

Shiny new UI. Docked gridviews are turning into WPF treeviews; the “Rubberduck” menu has been revamped, and under the hood, everything changed. Might as well make 2.0 look like as much change happened!

Code Inspections and Quick-Fixes that take the host application into account, giving recommendations tailored for a given host API. Also, some of the coolest inspections we envisioned as fantasies a year ago, are now possible to implement.

More refactoring tools like inline method, encapsulate field and promote local. The early minor releases of 2.x will likely see a new WPF/XAML UI for the refactorings issued in 1.x.


 

Something really good is cooking.

We’re also looking at implementing a more VBA-like Assert class, that would be more permissive with AreEqual and AreNotEqual than the current (C#-like strict) implementation is. Test results will be copied to clipboard or exported/serialized to XML with a simple click.

If you write some C# and would like to contribute to Rubberduck, note that our GitHub repository has a bunch of up-for-grabs issues opened, a lot of which are critical (i.e. no fix, no release) – the faster all functionalities work off the new command architecture, the faster we can deliver a pre-release…

Stay tuned!

Resolver: still not perfect

I just found another bug in the rewritten 1.4.x resolver, and as much as I want to fix it (and I will)… part of me can’t help thinking if you encounter this bug, your code has greater problems than mine.

Picture this code:

Sub Foo()
     Dim Foo As New Foo
     With Foo
         With .Foo
             .Foo = 42
         End With 
         Bar .Foo.Foo
     End With
End Sub

Believe it or not, it compiles… and the 1.4.1 resolver works perfectly and correctly identifies who’s who and who’s calling what. Now what if we added a recursive call?

Sub Foo()
     Dim Foo As New Foo
     With Foo
         With .Foo
             .Foo = 42
         End With 
         Bar .Foo.Foo
     End With
     Foo
End Sub

The bug here, is that this Foo gets resolved as a call to the local variable, so renaming the procedure to DoSomething would leave that Foo unchanged.

Not too bad. I mean, nobody in their right minds would ever do that. (right?)

However, it gets worse: if we change Sub to Function, in the name of being able to identify a function’s return value, a matching identifier within the body of a function (or property getter) is resolved to the function (or getter) itself… so this part needs to be refined at bit.

Function Foo()
     Dim Foo As New Foo
     With Foo
         With .Foo
             .Foo = 42
         End With 
         Bar .Foo.Foo
     End With
     Foo
End Function

Every single Foo here, with the sole exception of the local declaration, resolves to a reference to the function.

I hope this bug doesn’t affect your code… for your sake – and that of whoever will be maintaining your code in the future.

If it does… v1.4.2 with certainly include a fix for this issue.


Update

The non-resolving recursive call isn’t a bug:

it's a local!

Rubberduck, or Gummianka, le petit canard en caoutchouc

Next release rocks. Like, if you’re running 1.22, you’re not going to believe everything that’s coming at you in 1.4 – and if you’re running 1.3x, …you’re not going to believe it either.

The feature set is becoming massive, and that’s thoroughly awesome. We are currently in the final stages of stabilizing the next release and polishing everything. There’s a ton of amazing stuff coming, but one of the coolest things is that, thanks to the awesomeness of Code Review community members…

…we are proud to announce localization in French and Swedish, and a German translation is under way.

If a language isn’t supported on your system, it won’t show up in the display language dropdown:

Options-Localized

More announcements to come, stay tuned!