I've written a simple desktop application with C#/WPF and I'm now looking to create another, larger application which will share much of the functionality. I'm thinking that I should create three separate projects: one containing the shared code, and one each for the two apps.
My problem is that I'm not entirely familiar with .NET/WPF so I don't know if there are some best practices for this sort of thing. Can anyone offer some good sources of information, example projects or just some brief advice?
Edit: To put a little more detail on the scenario, the first application is a specialised editor and the second application is taking this file editor and wrapping a project model around it to create a sort of basic IDE.
Honestly it depends on what level the code you intend to share is. For instance, it's entirely plausable to put all of your business logic code into one project/class library and maintain it independantly, but mixing biz logic with WPF custom controls should be STRONGLY discouraged. Think about the layers of abstraction you are modularizing, and the dependancy heiarchy you are introducing and refactor accordingly.
Edit:
In response to your above changes I suggest the following: The logic and DAL associated with the above should be pushed into a project as seperate namespaces. The visual elements (the view, viewmodel) should most likely be moved into a seperate project and namespace set as well. Once you can merge these together and launch them from an exe that contains a host window and a UserControl for the rest of your hosted visual content, you can then probably move forward with integration into your larger IDE project. The key here is:
Visual Layer and View Logic -> Editor.Visual.dll
Biz Logic & Data Access -> Editor.Core.dll
I hope this helps.
Related
I will try to explain in as much detail as possible. There may be similar questions here on SO and I've gone through all of those but none of those have what I needed.
So, I'm starting out with a large scale C# MVC5 based Web Project and I want to organize everything in as much decoupled way as possible. For the database part I'm going to use Data Access ORM from Telerik (Previously known as Open Access) because I will be using MySQL for my project.
So far I have organized everything as below. I have defined solution level folders to divide the projects because I think there may be a possibility to have more projects in one layer in future.
**Solution**: td
- Business (Folder)
-- td.core (Project) (Contains Services and ViewModels)
-- td.interfaces (Project)
- Data (Folder)
-- td.data (Project) (Contains Database Models i.e. Telerik, Repository, Context Factory and Unit of Work class)
- Presentation (Folder)
-- td.ui (Project) (MVC5 Project, also Implemented IoC here)
- Shared (Folder)
-- td.common (Project)
Generally, when you bind models in your MVC project, if you have just one project in your solution, it works pretty easily without an issue.
i.e. in a MVC Controller
var obj = new TempClass();
return View(obj.getAllUsers());
and then in the corresponding view you use this at the top
#model (model type here)
When I separate all these layers in their own projects as mentioned above. The data layer would be the one directly communicating with the database hence I will generate the Telerik Data Access rlinq schema in my Data node where it will also generate the classes for the tables in my database (Default config)
Now, from the setup above, from the controller I'm supposed to call the Business layer to fetch the data and which will communicate with the Data node.
The question is that in the controller and in the view I will need the data types / references of the model I'm binding to. So, should I keep my automatically generated classes still in the Data node or can I move ONLY the generated classes to the Shared Node and then use those for the binding in the Controller/View? Which one is going to be a good practice? as I don't want to reference the Data nodes directly in the controller otherwise there is no point in separating everything like above.
Another quick question. I would be integrating so many third party APIs via REST/SOAP. In which layer should these best fit?
If anyone has any other Architectural suggestion or something that I'm missing here, please do suggest.
Thanks in advance everyone.
UPDATE!!!
Please see my updated architecture above.
Here's what I did so far.
I have added Repositories, Services and IoC.
In my Global.asax, I'm initializing the IoC which configures the Services etc for me.
My controller has an overloaded constructor now having the service from the business layer as the parameter.
Controller calls the service to get the data and the service calls the repository for it.
I have followed the generic repository path instead of creating repositories manually for each type
For 3rd party APIs, I will use the data layer and business later won't know where the data came from. It just needs to ask what it needs.
All this was made easier with the help of a dedicated Interfaces project which is being referenced from both the Business and Data layers when needed. Because as both want to implement abc interface I cannot declare it in either Business or Data layer since there would be circular referencing then which prevents me to reference both (Business/Data) projects to each other.
So, with the help of above changes, I can easily do what I want now and Everything is working perfectly as I want. Now the last question I have is
Is there any flaw in this architecture?
For a domain-centric architecture where it's easy to add another type of UI or change persistence technology and where business classes are easily testable in isolation, here's what I'd do :
Business layer with no dependencies. Defines business types and operations.
Data layer with data access objects/repositories that map from database to business types. You can also put your third party API accessors and adapters here. Depends on Business layer where repository interfaces are declared.
No Shared layer. Business types are the basic "currency" that flows through your system.
UI layer depending on the data access interfaces declared in the Business, but not on the Data layer. To decouple UI further, you can introduce an additional UI-agnostic Application layer.
You can read more about this at Onion Architecture or Hexagonal Architecture.
As it is, your architecture is pretty much data-driven (or Telerik Data driven) since the business and UI layers are tightly coupled to the Telerik schema. There's nothing wrong with that, but as I said in my comment, it enables other things such as quick development from an existing database schema, over full domain decoupling, framework agnosticism and testability.
Whether your Telerik generated model lives in the Data or Shared module makes little difference in that scenario IMO. It is still the reference model throughout your application and your controllers will be coupled to it anyway. The only thing I would advise against is moving the generated files manually - if it can be automated all the way, definitely do it or don't move the files at all.
I'm nether an expert for your special technologies, nor would I regard this as the ultimate answer, but I give you some hint's of the possibilities you may have (depending on your technologies):
Business should have exclusive access to data
Currently I don't really get, why your controller and view need access to any data-base related stuff at all? Shouldn't your business layer handle all of that and hide it from controller and view? But let's assume it's necessary for some reason.
Ways to split the data layer
You shouldn't move generated classes manually. You could change your generation-settings, to generate them elsewhere partially. But manually cherry-picking and moving them, results in an architecture which is hard to maintain.
The cleaner solution would be, if you can change the visibility of your classes. Can you generate classes with project or folder visibility instead? Or can you only export defined packages or classes in the project settings?
A workaround which requires more maintenance is the local extension. You could create new classes in your shared folder, which derive from the data layer classes.
Stucturing external APIs
Give them one or more own projects, so they are easier to change later. I know approaches where you have one main folder for each API. This makes each of them easy to change, but clutters your workspace. The important project will only be 4 out of 1000 projects. I normally prefer one folder containing all APIs. Thus the APIs are slightly harder to change, but your workspace stays clean. Your decision depends on two facts: how often do you change, add, remove or just study the APIs. And does your IDE provide a way to "hide" folders/projects from your workspace.
Hope this helps a little :)
I am trying to apply the onion architecture by J. Palermo, but I have a few things I am struggling with.
I have a few parts and I don't know exactly where to put these.
I have a plugin engine which reads a directory and determine what things to load en to do
Have some resource files with translations which are used in several projects. Where should I put these files?
I have some attributes which are used throughout the system. Where to put these?
I also have two 'base' controllers, some default results and views. Where should I put these?
All those items are used in several projects so I want to put the items at a central point.
My current solution structure looke like this:
Project.Core (contains the domain objects and interfaces of the repositories)
Project.Infrastructure (is the implementation of the core)
I am using MVC2.
I don't think it's something that the Onion architecture would solve by itself.
What I would do, is to put all these items in one or several projects, within another solution and build Nuget packages allowing me to deploy them everywhere I would need them.
This way I would have deployed items like your base controllers in your MVC project and plugin/translation stuff in your Infrastructure project.
That way, whenever you'll need to have those elements available in your newly created projects, you'll just have to deploy the package again.
Those items will become independent, stored in a central point (a new sln) and will have it's own release cycle!
I am currently developing a C# WPF project. The solution has two projects, one called GUI which contains all the Windows and GUI controls of the program and a second project called coding which contains all the classes and logic to ensure that if I change the logic, it doesn't affect the working of the GUI.
In the GUI project I have added a reference to the coding project and said using Coding, and this allows me to access the logic classes from the GUI screens.
However, if in the Coding logic class project I want to load a new window from the GUI project how do I go about doing this. If I try and add a reference to the GUI project from the coding project it says that this can't be done as it creates a circular dependency.
How can I reference both the projects together so that GUI can access logic classes from the coding project and reference the gui project from the coding project so the coding logic class can open a new window from the gui project.
Thanks for any help you can provide.
You can decouple it by introducing the third project Common and move out Window and other shared classes into it. Then Gui and Coding projects can easily reference Common.
BTW, try to rethink your design because I'm worried that Coding project is aware of UI entities.
EDIT:
In WPF you can decouple UI stuff from a logic by using Commands, see whether yu can achieve this.
When we talk about WPF and SOC "Seperation of Concerns" , this lead us directly to MVVM , here a simple explanation
I've read MEF documentation on Codeplex and I'm trying to figure out how to accomplish my task:
I would like to build an application framework that has standard components that can be used to do some common work (like displaying a list of records from a database). Plugins should be reused many times with different configuration each time. (eg. I have 5 windows in an application where I display record lists, each with different type of entity, different columns, each one should have it's own extension points like for displaying record details that should be satisfied with a different copy of another common plugin).
Is MEF suitable for such a scenario? How should I define contracts? Should I use metadata? Can I define relationships using configuration files?
Yes, you can use MEF. MEF supports NonShared instantiation of objects using the PartCreationPolicy attribute:
[PartCreationPolicy(CreationPolicy.NonShared)]
More information on this here.
Personally I'd do the wiring and configuration after the importing of the component on the target. However I am not sure how generic you want your application to be, if you are making a 'framework' to do certain solutions in I can imagine you want the configuration to be separate. You can go all-over-board and make an ISuperDuperGridConfiguration and import these on the constructor [ImportingConstructor] of your grid plugin. From within your target (where the grids get imported) set the location of the grid to the grid plugin (like main grid, side grid) and use the data stored in ISuperDuperGridConfiguration to further config the grid plugin itself.
However, you can easily go 'too far' with MEF, depending on your goals. We have a completely MEF componentized UI for an application with customized needs for every single customer. Sometimes I have the urge to put single buttons from the ribbon in a MEF extension.
As you can see, depending on your needs, you can and sometimes will go too far.
I don't think you'd need metadata especially in your case, but maybe someone else can share a different opinion on this ;-).
I hope this answers your question, if not please comment so I can highlight more aspects. All in all using MEF has been very positive for us, and we are using it far beyond a 'hello world' so to say. So at least you have that!
I have a sample ASP.NET application. The appliaction was developed as POC and not following any design and architectural standards.
Now I want to restructure the application. I can see some of the business logic and controls can be reused in future, such as login control.
I have two options for restructuring
I create a Utility DLL that will contain all such resusable code and another DLL that will contain all controls that can be reused.
I will create a separeate DLL for each type which can be reused e.g. Login control.
Which option is more better. Although I feel option 1 is good, but I need suggestion from experts.
I have no idea why you would want to keep a separate assembly per type. Don't do that.
Keep related functionality together in a single assembly. Look at how the .NET Framework is organized for examples. Note how, if you're not doing data access, you don't need to reference System.Data.dll.
There are multiple ways to build an architecture. For instance you can create horizontal layers which put all GUI logic, business logic and data logic into separate layers. This is only from logical perspective. Where to put the layers is another question. From OO perspective you put them in at least different classes. You can decide to put them in different name spaces, different project/assemblies.
Just start slowly and refactor the most obvious parts. You can start putting the classes together in a part of the project (folder). Then change namespaces. Then put them in seperate project. Small actions will give you the chance to further consider your options. Each improvement is one.
So my advice is to first arrange classes and namespaces within the current project and so shape the logical parts. Maybe you need to add some interfaces here and there as well to separate the layers.
I would go for a single assembly for your controls. You might create a new assembly for controls which you probably won't use soon or are very special.
I would categorize the business logic and make an assembly for each category.