Sorry for fading off for a few days. Having too much fun doing stuff!<div><br></div><div>A few responses:<br><br><div class="gmail_quote">On Thu, Sep 24, 2009 at 1:01 AM, Michael Giagnocavo <span dir="ltr"><<a href="mailto:mgg@giagnocavo.net">mgg@giagnocavo.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div lang="EN-US" link="blue" vlink="purple">
<div>
<p><span class="Apple-style-span" style="font-size: 15px; color: rgb(31, 73, 125); ">A few questions I have:</span></p>
<p><span class="Apple-style-span" style="font-size: 15px; color: rgb(31, 73, 125); ">Testability – is this even remotely practical?</span></p></div></div></blockquote><div>I've seen three areas of testability:</div><div>
1) Interop</div><div>2) Module Extensibility Framework</div><div>3) Modules and Plugins</div><div><br></div><div>The interop testability picture is not an area I'm very familiar. I imagine you could write a native mod_managed.dll testing shim and test against that. I think this would have some limited value. It would confirm that interop layers behaved as expected, but not much more. The biggest values would be a) verifying that the api doesn't change accidentally, and b) providing a good way of adding bug-solution cases when the behavior of the core is causing a failure that we need to provide some padding around.</div>
<div><br></div><div>The extensibility portion is very easy to write tests for. The module loader framework that I've refactored out of your code is completely stupid about the unmanaged code. It blindly passes the pointers through to the consumers that want them, and all of the module loader responsibilities are in managed code and mostly coded to interface. Very easy to mock and test.</div>
<div><br></div><div>Finally the plugin testability story. Currently this is harder, since the plugins are written to talk to a lot of static methods and direct unmanaged types. As things evolve, I'd want to create a updated plugin interface that passes all the interop points by interface. The unit testing responsibility for an app or api plugin should primarily be that for a given set of inputs or responses, it makes a specified set of calls. That should be possible to mock and test in managed code if we provide a thin managed interface layer over the P/Invoke|SWIG layer. I'm currently writing a plugin that does just this, but I have the interface layer inside my code. Not everyone should have to write their own though?</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div lang="EN-US" link="blue" vlink="purple"><div>
<p><span style="font-size:11.0pt;color:#1F497D">Modularity – I agree there are two parts. But, I think they are
pretty tightly coupled. The FS interface into unmanaged code is done via
unmanaged code and is really clear: App, Api, ApiBackground. The other ways I
can think of are FS-specific, such as XML binding interface and so on. But
those are things we should just add to the mod_managed core and be done with. I’m
thinking maybe we are talking about different things? Can you provide some user
stories that we want to cover with a pluggable loader/executor/etc.?</span></p></div></div></blockquote><div> I'm going to be a bit long-winded here. I hope I can clarify my intent, because I think I've been unclear on it so far.</div>
<div>A) Philosophy: I have two principal concepts that are guiding me in my push towards modularity.</div><div>1) Single Responsibility Principal: "Each class or code file should only have one reason to change." I don't think I'm quite here in the code I've shown you, but it's getting closer. (I could definitely use help.) The idea here is that the class that monitors the plugin directory shouldn't also load the files. The class that loads the files shouldn't be responsible for configuring and creating app domains. Neither of those classes should have concrete logging code in them. The good thing about this is that you don't have to worry about breaking the loader when you change the watcher, and vice-versa. If we later decide to change the watcher so that it only checks for updates manually, we don't need to even let the loader know.</div>
<div>2) Open-Closed Principal: "Classes should be open for extension and closed for modification." The idea here is that once we've written a working class that has it's bugs ironed out and it's unit tests written, we shouldn't (ideally) ever need to change it. If we need a new behavior, we can just subclass the original, or implement the same interface, or whatever, and use the new class instead of the old one. If everything is nice an loosely coupled, we can just slide the new implementation in for improved behavior without changing the old one. What this means for the module system is that we can create new functionality without breaking old functionality.</div>
<div><br></div><div>B) Actual uses: (Please note, that in most cases, I don't think that mod_managed needs to build out these functions, rather, I think mod_managed should "get out of the way" and let developers plug in what they want)</div>
<div>1) Commercial PBX Developer/Distributor:</div><div>Case: Say I want to write my own FreeSWITCH distro/UI/packaged software on Windows, and I want to do all of my development in managed code and I don't care about plugins or anything. </div>
<div>Answer: recompile my managed.dll with just a few changed lines in Loader.cs and your code controls everything coming into mod_managed. Ultimate power. Roll your own. Use it to launch a UI. Go nutz.</div><div>2) Complicated interwoven plugins:</div>
<div>Case: I want to write a bunch of plugin dlls and have them all cross-communicate and share caches and statics.</div><div>Answer: provide your own implementation of IModuleLoader and plug it into the registry. Now you can eliminate all of those pesky appdomains that prevent your cross-plugin communication. Sure, you'll have to reload the switch when you want to reload a plugin, but that's not such a big deal. (Or if it is, you can try loading all your plugins into the same appdomain and reload that every time. It's up to you.)</div>
<div>3) New and Improved(TM) Plugin Model</div><div>Case: You and I decide that the way we're calling the current plugins, passing them contexts and sessions, is completely dated and we want to change it to something new.</div>
<div>Answer: instead of changing the current plugin api, we just add a set of loaders and handlers for the New and Improved(TM) plugin interfaces. We roll that into the managed.dll. Now folk can write old plugins and new plugins, don't need to recompile, and everybody's happy. In a year or two we can start deprecating the old interfaces and get people moving to the modern ones, if we feel strongly about it.</div>
<div>4) Aspect oriented plugins</div><div>Case: I want to report every time a managed api call is made to a web service, and I don't want to change the existing plugin code.</div><div>Answer: write a new Execute and ExecuteBackground handler, and register it. Have your handler fire for _all_ arguments, rather than filtering on the first argument. Send your logging info off with a web service call.</div>
<div><br></div><div>These are all things that can be done with the structure I've outlined.</div><div><br></div><div>What may be more intersting than all of these, later, is plugins that interact with the event model to provide in-process ESL-type control of the FS.</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div lang="EN-US" link="blue" vlink="purple"><div><p><span style="font-size:11.0pt;color:#1F497D"> Thanks for
putting up with me!</span></p></div></div></blockquote><div><br></div><div>Thank _you_ for helping me get my thoughts out more clearly.</div><div><br></div><div>Josh </div></div></div>