patrickhuber / Pliant

MIT License
26 stars 4 forks source link

Support Dependency Injection in places where concrete implementations are used #60

Closed patrickhuber closed 2 years ago

patrickhuber commented 8 years ago

In order to provide a more decoupled architecture, support a platform agnostic form of dependency injection for instances where concrete classes are used.

bilsaboob commented 8 years ago

Hey,

While working on the "grammar workbench" I could do some refactoring to "decouple" some of the dependency if you would like?

I'm not sure if you have any concrete thoughts on how you would like to proceed in that case, but from Tooling perspective I think that the following structure could work ok.

This structure will be used according to:

If you agree on this, I'll start pulling out things into this specific structure - if you rather do it yourself at some point - that ok :) - just a thought, since I was thinking of starting on the "grammar workbench" anyway... and I'll get a feel for what I would need from the Pliant at that point anyway.

If you would like me to do this - then on to the next question - how do we sync the work? - my thoughts are that I would like to have "free reign" while doing this, and then let you pick whatever pieces you want and do any renaming refactoring you feel necessary?

Any thoughts?

bilsaboob commented 8 years ago

Btw, do you have any preferred libraries for: (I'll be using this for the grammar workbench - I guess it would be useful to use the same in case you want it in the Pliant libs at some point)

patrickhuber commented 8 years ago

I have a similar approach in mind. I tried to keep things in isolated folders so those are the first level of grouping. I'll lay out how things are currently structured and we can see what the lines are and what assembly it makes sense to push them into in order to achieve some feature by consumers.

Here is the dependency graph: pliant-dependencies

(I'll edit this if you see something I missed)

If you aren't partial to the "Lib" suffix, I'd like to keep it out in favor of just Pliant.*. The runtime folder was just to keep IParseEngine and its supporting classes out of the project root, but it is still just a library.

For contributions, yes a fork of the development branch is probably the best place to start. In other projects I've seen them create pull request very early so that any changesets are updated and we can go over the changes. You or I can make comments before the pull request is accepted. The nice thing about that is the changes are added to the pull request automatically. That way its not a big huge pull request that takes forever to review and we can incrementally improve the code before submission. It also gives me enough time to update the CI build and CD pipeline for the NuGet package / packages.

For the DI I usually don't directly reference a DI framework and instead create a interface called IDependencyResolver.

So as a start:

public namespace Pliant.Ioc
{
   public interface IDependencyResolver
   {
         T GetService<T>();
         T GetService<T>(string name);
         object GetService(Type type);
         object GetService(Type type, string name);         
   }
}

Then, a consumer would create a binding library like Pliant.AutoFac or Pliant.Workbench.AutoFac and implement IDependencyResolver. That way we can reduce coupling and allow the user to specify the DI container of their choice. I sometimes will implement some additional Resolve methods and wire up a simple dictionary for unit tests, etc. I used to do a lot of NHibernate and they had a similar philosophy: provide an interface and provide a default implementation. Allow the user to override.

Logging, similar approach. Currently I use System.Diagnostics.Trace for the grammar execution and only log on Debug. There is a huge performance hit in doing logging during the core loop, so I had to make sure I wasn't doing any memory allocations or anything in there. If there as a ILogger interface in the Common/Core library, I could reference that instead and rely on DI to provide a NullLogger or something from one of the logging frameworks.

For Database, I'm not sure I have a strict preference. I probably use sql server too much :). A similar plugin model to DI could be used. As long as the implementation of the persistence layer is abstract enough. Entity framework and System.Data.Common already do a pretty good job of abstraction, so as long as you code to one of those and try to keep implementation detail (DDL etc) out of the generic implementation you should be fine.

I don't really have a preference on UI. I went the web track with my career. I've messed around with WPF, never with MVVM Cross. Is cross platform a concern? I've been thinking about a .NET core port but was waiting for the .net core tooling to hit GA.

bilsaboob commented 8 years ago

Hey, ok, sounds good to me :)

I'll give you a ping in the weekend once I'll start setting things up - perhaps we could stay in touch on Skype or so? - my profile name is "bilsaboob", feel free to add me!

Regards, /Peter

bilsaboob commented 7 years ago

Hey,

I've started on setting up the projects / repos and such.

Currently I've setup the following structure:

You can view the repositories on my github.

Honestly I'm not entirely sure on how to handle the dependencies between github projects - my ideal situation would have been:

One thing that came to mind is that perhaps we could use some better way for communication rather than writing here on the forum? - in order to follow up on changes / progress we are making? )

I would rather it not becoming a forced "jira" project or so :) - though perhaps have some screensharing / meeting every now and then on skype - walking through the change an such? (of course I don't want to make this a big overhead, basically just whenever someone feels the need for it... and we are able to fit it into our schedules...?

Regards, /Peter

patrickhuber commented 7 years ago

I created a Gitter feed. From what I've seen its pretty common among the github community to do chat there. I'll end up putting the badge on the readme.md file. https://gitter.im/Pliant-net/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link.

Haven't looked at Paket yet, I need to research it a bit more. I usually just use NuGet packages to share common libraries but that may not work with the workflow you are proposing. I keep going back to git submodules, but perhaps Paket will be the best option.

bilsa commented 7 years ago

Yep, i was thinking of subrepositories too - though i was mercurial - I'll hav a look at it for github too - if nothing else, paket seems like a tool to keep an eye on :) - i like the Idea of beeing able to have an intuitive config file - and to manage references to GitHub projects as if nuget packages ... anyway, I'll get back on this later in the gitter channel