Starting with ASP.Net 5, I wanted to lay the foundation to my project. As of now, I created 2 projects.
Project - The WebApi project that comes with a Startup class.
Project.Server - A dll project that will hold all the business logic.
At first I though I should write a Bootstrapper class in "Project.Server" that will allow me to hide many parts of that dll (that "Project" doesn't need to know about), but then I found myself thinking I may be doing some extra work; In "Project"'s Startup class I'm calling many of my Bootstrapper class.
Does this extra layer of abstraction needed in a WebApi project?
Although "Project.Server" is currently only referenced in "Project", but I still want to structure is correctly...
Different people will have different opinions on how to structure your web app. Personally, for me, it's a matter of how much work is involved. If it's fairly easy for you to separate out your business logic into a separate DLL, then do it. Even though there may not be any immediate advantages now (since Project is the only consumer of Project.Server), in the future, if you ever decide there needs to be another consumer of the business logic, it will be a lot easier to make that work. However, if it's a lot of work to create this extra layer, then I'd say it's not worth it, since you can't really predict what the future might bring, and so why spend a ton of effort trying to code for a future that is unknown.
Related
I have a project with the following structure:
Main Rest
Main Services
Second Rest
Second Services
Third Rest
Third Services
Fourth....
Data Layer
etc
In terms of dependency, all Rest layers can access the Main Services and their own Service eg Second Rest can access Second and Main Services but not Third, and so on.
The issue I am facing now is that increasingly Second Services needs to access parts of the code in Third Services and so on.
The temptation is to move that code from Second Services to Main Services-but this does not seem right to me and is making me question if this separation and if it is useful.
I also dont think it is quite right to move all the code in one big Service and have everything access it from there.
One thing I did think of was an Inter Project Service layer that can provide the link between the Service Layers, but realistically I would need one of these for each of the Services to avoid circular references.
Finally, to complicate matters further I have to thing about Dependency Injection and the different implementations of interfaces between projects.
Has anyone experienced this kind of issue with a good solution?
Refactoring the whole project is not an option as I have to consider business needs and it does not make sense to do this financially.
I had experience refactoring big pile of mud, where everything was entangled. One thing that I've found most helpful was to invert dependencies for functions / methods too. If Rest2 calls Service2.Foo which wants data from Service1, the it's Rest2's job to bring the data.
To further enforce this approach, combat temptation to write and use various utility and convenience functions, that do cross-service calls for you, or at least keep these function private for each module.
This somewhat aligns with idea of CQS, extrapolated even further: each function is either doing some job independently or orchestrates whole team (as big as needed) of workers.
The noticeable downside of this approach is increased size of "flattened" top-level functions, but in my case it was much smaller problem than entanglement.
Ideally, this approach should yield set of modules organized in hierarchy of layers, where no module is allowed to call it's siblings or higher layers. Non-cyclic data flows are much easier to reason about!
I'm wondering why the most common stuff/basic logic is not just put to Product. Is creating Product.Core and putting nothing directly in Product done only to imply what classes are really about? Is there any "rules"/best practices about this?
It's a simple question, but I'm not sure if my writing make any sense.
EDIT: If I have 3 things to divide in namespaces: GUI, DataAccess and Business logic and decide to have classes in 3 namespaces. First 2 are obvious:
Product.UI
Product.DataAccess
However business logic can be put either to
Product.Core
or
Product
Now I would like to know which is more "standard": Having Business logic in Product or in Product.Core.
In case of putting Business logic classes in Product there would be no Product.Core.
If putting Business logic classes in Product.Core the Product would contain no classes.
Both approaches can have some benefits and I would like to know what people think.
There is some good discussion here https://softwareengineering.stackexchange.com/questions/40394/how-do-you-organize-your-projects about that.
One point is to separate the solution as much as you need to for further expansion - but it is generally easier to refactor on the fly as you need to. Otherwise, there are two main reasons to separate projects:
1. Following a separation of concerns paradigm
For example in a simple web project, I would have 2 projects Project and Project.Core. This allows me to keep all the data, logic and code in one project while keeping all the web stuff in another.
2. Having shared code amongst individual consumer/frontend applications
If you plan on having a web application and a windows service for instance, you are going to have common code in the realm of services and data access. Instead of duplicating this code you can move it to a common library so that both applications can take advantage of the same code.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I am in the very early phases of a WinForms product rewrite, and I am trying to determine the "best" strategy for implementing a new solution structure. The current solution contains 50+ projects, and (for the most part) it contains all of the logic required to run the application. Several of the projects do have dependencies to projects that exist in a separate "Framework" solution, but that is being replaced / modified as well.
As I said, the current solution produces a WinForms product; furthermore everything is tightly coupled together, front to back. Additionally, we want to start offering a Web / Mobile solution in addition to/alongside our WinForms product. Because of the desired changes, I am considering breaking this out into several separate solutions. Details follow.
Product.Framework Solution becomes Product.Core - A shared set of assemblies containing common interfaces, enums, structs, "helpers", etc.
Product.Windows - MVC pattern. Contains all views and business logic necessary to run the WinForms product.
Product.Web - MVC Pattern. Contains all views and business logic necessary to run the Web product.
Product.Services - Hostable WCF services. Contains the public service layer that Web/Win/Mobile call into with the underlying DAL.
This is where I am looking for a sanity check: I am planning on implementing DI/IoC in both the WinForms and Web project (I am not so much worried about injecting into the WCF services); in my mind it makes sense to have interfaces of all the concrete entities (representation of database tables) and services in the Product.Core solution. The only reference I would possibly need to Product.Services in the Web and Winforms solutions would be to register the concrete types with the container.
Does this make sense? Is there something glaring that I have overlooked? Thank you for any and all feedback!
The way I think about solutions is "all of the things necessary to run my program". In your case, your WinForms application is the final step. The goal is to be able to run the output executable from that project. The solution, then, should consist of every project necessary in order to build that executable from scratch. The last thing you want is to have a new developer have to checkout your source code from version control and then have to use tribal knowledge to figure out which solutions need to be built in which order and then how to tie them all together.
Now you mentioned that you may be adding some more final step applications such as a web application. Assuming that the dependencies for your WinForms application are similar to your web application, I am of the opinion that you should just add the web application to the same solution as your WinForms application. However, sometimes it makes sense to have a different solution for each, and then have each solution reference a similar set of projects.
One of the key things to remember is that when a project dependency is introduced, you will need to update all of your solutions to have that new dependency. This is the primary reason why I tend to have a single solution for most things.
Don't forget, in Visual Studio you can have solution folders to help you visually manage the solution as a whole. Also, you can utilize the build configurations and dependency tree such that building doesn't require compiling everything when you only need one final project built. Finally, you can utilize the Set Startup Project option to switch between which final output you want to work with.
Remember, any given project can very easily be part of multiple solutions. If you have a core set of frameworks that are used across an array of different products you can include the framework projects in each "Product" solution. If the framework is not primarily worked on by the same team that uses it you may want to consider splitting the framework into a separate repository and only distribute the output assemblies (which would be committed into other repositories and referenced in your other solutions).
In general, my opinion is to have a single solution for everything and utilize various features of Visual Studio so managing such a large and complex solution isn't very painful. The one thing I would advise against is having the build of one solution depend on the build output of another solution. If you are doing this, the two projects should reside in separate repositories and the build output should be copied and committed as needed (basically treat the output as a 3rd party library).
There is no "best" answer here. Here is an observation from your question:
Why do you need an interface for all concrete entities?
It appears that these are just data model classes. Unless you are looking to Mock these classes or write generic methods(or classes) that can operate on a category of classes such as all data model classes that implement an IEntity interface for instance so that you can constrain your generic method/class by the data model type.
Example:
public void MyGenericMethod<T>(T t) : where T:IEntity{ // do something}
It sounds like the refactoring / restructuring you are doing will have major impact on the business you are working for and the design/ architectural decisions made now will need to sustainable for the business as it evolves. I would highly suggest involving an architect in this process who can understand the needs and the nature of the business and come up with a game plan accordingly.
I've been struggling to do this in a way that fulfills all of my requirements.
Here is what we have in our library:
Base classes for controllers and services
Business objects (stores, departments, etc)
Common Partial Views (Login, Error, etc)
Base class for HttpApplication
General common code (read an INI file, create a db conn, etc)
The one requirement that has been giving me trouble is as follows:
Lives in one place on a server. (i.e. copy local = false)
This breaks because:
The DLL containing the HttpApplication class must be in the same directory as the web apps dll to launch. I haven't found a way around that. I'm ok with duplicating this code in every app, but would rather not.
The shared views don't like to work if I use Assembly.LoadFrom() to load the dll from the shared location. (I've been using this method to precompile my views)
Any namespace shortcuts in web.config break at runtime with compilation errors because the web.config is parsed before the assembly is loaded.
My question to you folks is how do you handle your common code in a similar environment?
The GAC seems to be more trouble than its worth, and we want all of our apps to be using the same code, and not have multiple apps on multiple versions and have to maintain all of that. Are there design patters/best practices that can guide us in this regard?
Also, as a bonus, if you can solve any of the problems above, that would be great, too.
Thanks!
Edit: I guess a question that follows is whether or not we should even have a directory with the common dll(s) on the server, or if they should only be deployed as projects are deployed/updated?
Firstly, you will want to separate out what you're trying to achieve. Don't create 1 library that does everything or you will have a Big Ball of Mud. Don't be afraid to create several maintainable libraries to achieve what you're after. Is there a specific reason it needs to be stored in one location?
For example, several of the items you mention are MVC or web specific. If you have items that can be reused by MVC, create a class library that contains MVC base classes you inherit and reference them in your project. Use the single responsibility principle as much as possible.
Regarding the other items you mentioned, like database connectivity, if it's reusable, abstract it out in a data access class library and reference it. Other simple operations like reading an ini file or creating a file, create another library and abstract it to easy to use methods.
I prefer to copy the library dlls locally. You never know when you will need to make changes to the library, but you don't want all of your projects to stop compiling. When you're ready to implement a new version of the library, copy the dll in and recompile.
Not sure why all the hate towards the gac. It was designed to handle this specific problem. Install your common dlls to the gac and all apps can see them. Need to deploy a new one, just re-install it in one place.
I have a large .NET web application. The system has projects for different intentions (e.g. CMS, Forum, eCommerce), and I have noticed a (naive) pattern of calling on another project's class. For example, the ecommerce module needs functionality to generate a file on the fly for products, and I call and reference a method in the CMS to do this, because file handling is really a job for the CMS.
Obviously (and I know why), this is bad design and a case of high coupling.
I know a few ways to handle high coupling, like restructuring the project (although I don't really think this is a robust solution), but what else can I do to reduce high coupling? Any simple tips? Also, it would be good to know why/how they reduce coupling. I use .NET 3.5 and Sql Server 2005 so things like JMS (which I keep coming across in my search for tips on this design issue), are not applicable.
Thanks
BTW,
One of the reasons I ask this is that I have read the previous questions similar to this but usually if a question that has been asked before is asked again, different tips can be learnt as different people reply to the post.
I know of dependency injection/IOC, but I am interested in the small things that can be done to reduce coupling.
How could I choose between using a static class, or an interface-derived class, or the IOC approach when deciding on how to reduce coupling? Also, I could develop a web service which could call a static class - mixing up the approaches in my solution.
The interesting thing is that in my application, I don't want it to be disjointed. So I just have a forum, ecommerce system, and any other module required, but everything has to gel into one site so each module (which is represented as a dedicated project in my Visual Studio solution) needs to know about every other module and work with it. So for example, I might have a module which handles user profiles (working with ASP.NET membership, roles, etc), but this will work with the forum module as a user on the forum will be a registered user on the site (one login throughout), and his or her profile will be coming from the user profile module. This is as opposed to seperate profiles as seen on other sites I've come across).
You should expose web services in those projects who will be needed by other projects. This is kind of the base level idea behind SOA. So, I would just create web services and consume them, which will decouple you quite a bit from how you have it now. Hope this helps.
I'd consider starting by doing an "extract interface" refactoring on the tightly coupled pieces. For example, if using the CMS as a backing store, create an interface that can store things, then create a mediator or adapter class that knows about the CMS, but isolate the logic that knows about the storage mechanism details to just that class.
Then, for testing, you can easily substitute an in-memory store or local-filesystem store that doesn't depend on the CMS being up.
Consider using techniques like dependency injection (See StructureMap, Spring.Net, NInject) to simplify instantiation if a simple factory doesn't give you the flexibility you need.
It sounds like you have a layering problem. Your assemblies should have a single dependency cycle - from least stable to most stable. That allows you to version sensibly. Generally, that cycle would be something like UI (least stable) -> Domain Core (stable) -> Data Access (most stable). You can throw in a Utilities or some infrastructre assemblies along the way, but again - they should be considered more stable than the assemblies dependent on them.
I'd guess your App.ECommerce and App.Cms assemblies are more siblings than layers - so you would not want those to depend on each other, but that doesn't mean you can't reuse functionality. For your particular scenario, you need to push the needed functionality down to a Core or Utilities assembly that both ECommerce and Cms can depend on. If it's a specific implementation that ECommerce provides, then you can push an interface or abstract base class to the Core - and have a higher layer (perhaps IoC container) wire up the concrete Cms.FileCreator class to the ECommerce.IFileCreator dependency.
Get proper abstractions in place as described by others (interfaces, etc). Program against abstractions, not concretions.
Design your classes with Dependency Injection in mind as you have described.
Use an Inversion of Control Container as the mortar between the bricks.
Unity from the Patterns & Practices team complements the Enterprise Library.
Scott Hanselman has a nice List of .NET Inversion of Control Containers.
Well, I don't know anything about .NET, but how about refactoring common code into a separate, underlaying project/layer? Loads of stuff in a web app can be done generically to suit both a CMS, a forum and eCommerce, writing to a file is a perfect example.
Another approach could be to see the forum and eCommerce as modules in a CMS, which would also make sense. Then they could safely use specified API:s of the CMS.