aherd2985/UtilityBelt

Rearchitecture with System.Composition (MEF)

Closed this issue · 6 comments

ktos commented

At the moment the Program.cs is around 1000 lines and will be growing with adding more and more utilities, which is... unfortunate. Of course you may move separate utilities into separate classes, yet still the main menu will require adding something by hand with each new utility, so it kinda misses a point of being extensible without further changes.

So I propose to try rearchitecture this application using System.Composition aka MEF (Microsoft Extension Framework). This will allow to create an interface, e.g.:

public interface IUtility
{
    void Configure(IOptions<SecretsModel> options);
    void Run();
    IList<string> Commands { get; }
}

And now the implementation can be something like that (on the example of cat fact):

[Export(typeof(IUtility))]
public class CatFact : IUtility
{
    public IList<string> Commands => new List<string> { "cat", "cat fact" };

    public void Configure(IOptions<SecretsModel> options)
    {
        // nothing, as it is not used in cat facts
    }

    public void Run()
    {
        // here doing the all things just like CatFact() right now
    }
}

And because of [Export] attribute, we can use [ImportMany] and automatically import everything into some kind of List<IUtility> - and then dynamically generate menu based on some kind of Dictionary<string, IUtility>.

All classes marked with [Export] from the current assembly (or may be divided even into multiple assemblies, to work as plugins, BTW) will be imported into that list - so each utility may be separated into separate class.

Of course it will increase the complexity a bit (as there won't be any more just switch and just static methods in Program but separate class for every utility with an attribute), so I am not sure if it's desirable for this project, so this is why I am just throwing here this concept -- but I can try to make some prototype PR if you wish.

There will be a breaking change -- with new, automatically generated menu, the numbers of utilities will change, so there won't be "4" for "cat facts" anymore.

Same problem for me, I think it's the rigth use case for MEF using

I think this could be a great idea; it has become cumbersome handling every merge.

I would believe with thorough documentation, we can still keep this accessible for anyone to contribute.

Thank you for the great idea, and any help you could offer in setting this up!

ktos commented

Okay, so I prepared the prototype implementation - you can see it in #67 along with some first utilities "ported" to a new system.

This would be a big improvement. The modular structure is easy to follow along with and it's scalable.

Hopefully we could get some help through Hacktoberfest with the re-write and/or expansions!

We would only need to keep removing the methods from Program.cs to follow the new architecture.

Should we pull the trigger, push this through, and work on the re-write?

ktos commented

If you think that's okay, go merge #67, I changed the title a bit to more accurately reflect what's going on.

It seems there are no more PRs at the moment with new expansions so we can concentrate on moving everything to the new architecture.

This was a great idea and has helped tremendously with code changes. It has saved me a lot of time already, thank you for doing this!