I keep hearing about the DRY Principle and how it is so important in ASP.NET MVC, but when I do research on Google I don't seem to quite understand exactly how it applies to MVC.
From what I've read its not really the copy & paste code smell, which I thought it was, but it is more than that.
Can any of you give some insight into how I might use the DRY Principle in my ASP.NET MVC application?
DRY just means "Don't Repeat Yourself". Make sure that when you write code, you only write it one time. If you find yourself writing similar functionality in all of your Controller classes, make a base controller class that has the functionality and then inherit from it, or move the functionality into another class and call it from there instead of repeating it in all the controllers.
use filter attributes to manage aspects (authentication, navigation, breadcrumbs, etc)
use a layer supertype controller (apply common controller-level filters to it, see mvccontrib for an example)
write custom actionresults (like in mvccontrib - for example we made one called logoutresult that just does a FormsAuthentication.Logout()
use a convention for view names
most importantly - keep you controller actions dumb, look for reuse opportunities in services
Don't Repeat Yourself. It can apply to many different aspects of programming. The most basic level of this is prevent code smell. I haven't used ASP.NET so I can't get specific to it and MVC's.
In C++ Templating prevets multiple copies of the same function.
In C void * pointers can be used in a similar fashion, but with great care.
Inheriting from another function allows function allows other functions to use the same code base without having to copy the code.
Normalizing data in a database minimizes redundant data. Also adhereing to the DRY principle.
When you go over a "thought" in a project. Ask yourself.
Have I already wrote this code?
Will this code be useful elsewhere.
Can I save coding by building off of a previous class/function.
DRY is not specific to any one technology. Just make sure you look at your classes from a functionality standpoint (not even from a copy/paste coder view) and see where the duplication occurs. This process will probably not happen in one sitting, and you will only notice duplication after reviewing your code several months later when adding a new feature. If you have unit tests, you should have no fear in removing that duplication.
One advantage of MVC as related to not repeating yourself is that your controller can do tasks common to all pages in the one class. For example, validating against certain types of malicious requests or validating authentication can be centralized.
DRY should not only be applied to code, but to information in general. Are you repeating things in your build system? Do you have data which should be moved to a common configuration file, etc.
Well, the most common example that I can give about DRY and UI is using things like MasterPages and UserControls.
MasterPages ensure that you have written all the static HTML only once.
UserControls ensure reusability of code. Example, you will have a lot of forms doing basic stuff like CRUD. Now, ideally we want all users to see different pages for Create and Update though the forms fields in both will almost be the same. What we can do is combine all the common controls and put them into a control that can be reused over both the pages. This ensures that we are never retyping (or copy-pasting) the same code.
DRY is especially important in MVC because of the increase in the sheer number of files to accomplish the same task.
There seems to be a misconception that everything in a domain model has to be copied up as a special view model. You can have domain models be domain models but view models be something that know nothing of domain specifics and be more generic. For example:
Domain Model classes: Account, Asset, PurchaseOrder
View Model: List, Table, Tuple, SearchFormBackingModel:Checked options, Outputoptions, etc. The view itself might be much more view implementation specific.
The Tuple/Dictonary/Map might map to Account, Asset and PurchaseOrder single instances but a Table might be useful for a collection of them etc. You still have MVC but you have session data, not ready for transaction yet in a view model without necessarily having it violate the rules of your domain model which is where the rules should go. They will be less anemic and anti-pattern that way. You can pass these rules up front and use them there or just in back or both depending on how the system reads from clients etc.
Related
Most MVC tutorials I've been reading seem to create 4 View objects for each Model. For example, if my Model is "Foo", there seem to be 4 .cshtml files: Foo/Create, Foo/Delete, Foo/Details, and Foo/Edit. Using the VisualStudio "scaffolding" helper does this as well.
Is this really considered MVC best-practice? It just feels wrong to have 4 classes that are 80-90% identical to each other. When I add a new field to Foo, I need to edit all 4 .cshtml files. This sort of dual-maintenance (quad-maintenance?) just makes my OO skin crawl.
Please tell me: is there an expected/accepted best-practice which handles this differently? Or, if this really IS accepted best-practice, tell me why the quad-maintance shouldn't make me squirm.
I'm a reasonably skilled veteran of ASP.NET / c# / OO Design, but pretty new to MVC; so apologies if this is a noob question. Thanks in advance for your help!
Edit: thanks for all the replies! I marked the most thorough one as the answer, but upvoted all that were helpful.
You'll probably need between two and four different views:
List (for viewing many things)
View (for viewing a single thing. Might not be necessary, if it's OK to use Edit as View, or if List has room to show all properties)
Create
Edit (can be the same as create, if you code cleverly)
Thus, if your model doesn't have too many properties to show them all in a table, and if you're OK with not having a static, non-editable view for just examining, you can get well away with just List and Edit, and scrap the other two.
However, this doesn't solve your problem of double (or triple) maintenance if you update your model. There's other magic for that ;)
In ASP.NET MVC 3, there are extensions on HtmlHelper that let you do Html.DisplayForModel() and Html.EditorForModel(). These use predefined templates to nest themselves into your object and draw up display/edit fields for all public properites. If you pass DisplayForModel an IEnumerable<Foo>, it will create a table with column headers that are the property names of Foo (using the DisplayName attribute information if you supplied it) and where each row represent one Foo instance. If you give EditorForModel a Foo, it will create a <label> and an <input> for each public property on Foo.
All of the templates used by these powerful extension methods can be replaced by you, if you're not happy with the defaults. This can be done either on the level of Foo, in which case you'd be back in your double-maintenance scenario, or on lower levels (such as string or DateTime) to affect all editor/display fields generated with the templates.
For more information on exactly how this works, google "ASP.NET MVC 3 editor templates" and read a couple of tutorials. They'll explain the details much better than I could.
The views that ASP.NET MVC create for you don't necessarily need to be the views that you use in production. I found those just to be handy while developing quick prototypes or to test the database CRUD operations. Feel free to create whatever view(s) you would like to handle the operations.
I would generally just have 1 or 2 views to handle the basic operations and not use the built in views that are generated. For example, 1 view for adding, editing, or details and 1 view to show a list of objects.
It all depends on your application.
If you have a single item, you don't need a List view. If you can't edit it, then you don't need an edit view. Create and Edit can often be the same view, unless there are special things you need to do in one, but not the other.
In other words, use as many views as you need. There's no hard and fast rule here. The scaffolding is just there to help you on your way. Many kinds of apps will work just fine using the scaffolding, and won't require advanced HTML or Javascript.
Why would you want multiple views? Well, let's take the display and edit functions. You could create one view, in which you use if statements to determine the edit mode of the view, however this will complicated the view logic and views should be as simple as possible.
The reason to create seperate views is that its easier to maintain than one gigantic view with tons of conditional logic in it.
You can use exactly the same view when you are performing [HttpGet]. Given that you pass a proper ViewModel to this view, it will populate with appropriate data every time whether you are loading create, update, or delete Action.
The problem becomes apparent when you try to post that data to a specific Action.
Naturally View should have only one form, which will be used for posting data. When you declare this form, you specify which exactly Action to use for Post.
Having 3 different Submit buttons in that form will not make a difference since all of them will post the same form to the same Action.
You could do some javascript tweaking on OnClick event for these buttons to change Action to which data is posted, but this definitively would not be best practice.
Buttom line: having 4 different views for each of the CRUD actions is the best practice for MVC.
I tend to create the following for an object's CRUD ops:
index
_form (partial)
new
update
delete
view
As the same form is shared between new and update, there is very little difference between the two. It really depends on how much you want the variation to be, honestly.
As for delete, this is optional. I like to have a view in case javascript is disabled.
edit:
You mention view models and the guy above posted a long, convoluted (no offense) VM code sample.
Personally, I hate classes written to basically mirror domain objects and are only used to "move" data. I hate VMs. I hate DTOs. I hate everything that makes me have to write more code than is necessary.
I guess I've drank the coolaid of other frameworks (rails, sinatra, node.js) to the point where I can't stomach the idea of tossing DRY to the wind.
I personally say skip um.
Edit2 I forgot list..
So, I need some input refactoring an asp.net (c#) application that is basically a framework for creating dynamic forms (any forms). From a high level point of view, there is a table that has the forms, and then there is a table that has all the form fields, where it is one to many between the two. There is a validation table, where each field can have multiple types of validation, and it is a one to many from the form fields table to the validation table.
So the issue is that this application has been sold as the be-all-end-all customizable solution to all the clients. So, the idea is whatever form they want, we can build it jsut using DB configurations. The thing is, that is not always possible, because there is complex relationship between the fields, and complex relationship between the forms themselves. Also, there is only once codebase, and this is for multiple clients - all of whom host it on their own. There is very specific logic for each of the clients, and they are ALL in the same codebase, with no real separation. Sometimes it was too difficult to make it generic, so there are instances where it has hard coded logic (as in if formID = XXX then do _). You can also have nested forms, as in, one set of fields on its own within each form.
So usually, when one client requests a change, we make the change and deploy it to that client - but then another client requests a different change, and we make the change and deploy it for THAT client, but the change from the earlier client breaks it, and its a headache trying to debug, because EVERYTHING is dynamic. There is no way we can rollback the earlier change, because then the other client would be screwed.
Its not done in a real 3-tier architecture - its a web site with references to a DB class, and a class library. There is business logic in the web site itself, in the class library, and the database stored procs (Validation is done in the stored procs).
I've been put in charge of re-organizing the whole thing, and these are my thoughts/questions:
I think this is a bad model in general, because one of the things I heard one of the developers say is that anytime any client makes a change, we should deploy to everybody - but that is not realistic, if we have say 20 clients - there will need to be regression testing on EVERYTHING, since we don't know the impact...
There are about 100 forms in total, and their is some similarity in them (not much). But I think the idea that a dynamic engine can solve ALL form requests was not realistic as well. Clients come up with the most weird requests. For example, they have this engine doing a regular data entry form AND a search form.
There is a lot of preserving state between pages, and it is all done using session variables, which is ok, except that it is not really tracked, and so sessions from the same user keep getting overwritten, and I think sessions should be got rid of.
Should I really just rewrite the whole thing? This app is about 3 years old, and there has been lots of testing and things done, and serious business logic implemented, so I hate to get rid of all that (joel's advice). But its really a mess of a sphagetti code, and everything takes forever to do, and things break all the time because of minor changes.
I've been reading Martin Fowlers "Refactoring" and Michael Feathers "working effectively with legacy code" - and they are good, but I feel they were written for an application that was 'slightly' better architected, where it is still a 3-tiered architecture, and there is 'some' resemblance of logic..
Thoughts/input anyone?
Oh, and "Help!"
My current project sounds like almost exactly the same product you're describing. Fortunately, I learned most of my hardest lessons on a former product, and so I was able to start my current project with a clean slate. You should probably read through my answer to this question, which describes my experiences, and the lessons I learned.
The main thing to focus on is the idea that you are building a product. If you can't find a way to implement a particular feature using your current product feature set, you need to spend some additional time thinking about how you could turn this custom one-off feature into a configurable feature that can benefit all (or at least many) of your clients.
So:
If you're referring to the model of being able to create a fully customizable form that makes client-specific code almost unnecessary, that model is perfectly valid and I have a maintainable working product with real, paying clients that can prove it. Regression testing is performed on specific features and configuration combinations, rather than a specific client implementation. The key pieces that make this possible are:
An administrative interface that is effective at disallowing problematic combinations of configuration options.
A rules engine that allows certain actions in the system to invoke customizable triggers and cause other actions to happen.
An Integration framework that allows data to be pulled from a variety of sources and pushed to a variety of sources in a configurable manner.
The option to inject custom code as a plugin when absolutely necessary.
Yes, clients come up with weird requests. It's usually worthwhile to suggest alternative solutions that will still solve the client's problem while still allowing your product to be robust and configurable for other clients. Sometimes you just have to push back. Other times you'll have to do what they say, but use wise architectural practices to minimize the impact this could have on other client code.
Minimize use of the session to track state. Each page should have enough information on it to track the current page's state. Information that needs to persist even if the user clicks "Back" and starts doing something else should be stored in a database. I have found it useful, however, to keep a sort of breadcrumb tree on the session, to track how users got to a specific place and where to take them back to when they finish. But the ID of the node they're actually on currently needs to be persisted on a page-by-page basis, and sent back with each request, so weird things don't happen when the user is browsing to different pages in different tabs.
Use incremental refactoring. You may end up re-writing the whole thing twice by the time you're done, or you may never really "finish" the refactoring. But in the meantime, everything will still work, and you'll have new features every so often. As a rule, rewriting the whole thing will take you several times as long as you think it will, so don't try to take the whole thing in a single bite.
I have a number of similar apps for building dynamic forms that I support.
There's a whole lot of things you could/could not do & you're right to think hard before throwing away 3 years of testing/development.
My input for you to consider is to implement a plug-in architecture on top of what you're got. Any custom code for a form goes in the plug-in & the name of this plug-in is stored with the form. When you generate a form, the correct plug-in is called to enhance the base functionality. that way you get to move all the custom code out of the existing library. It should also mean less breaking changes, each plug-in only affects the form it's attached to.
From that point it'll be easy to refactor the core engine as it's common functionality across all clients & forms.
Since your application seems to have become a big ball of mud, a complete (or an almost complete rewrite) might make sense.
You should also take into account new technologies like document-oriented databases (couchDB, MongoDB)
Most of the form definitions could probably fit pretty well in document-oriented databases. For exemple:
To define a customer form, you could use a document that looks like:
{Type:"FormDefinition",
EntityType: "Customer",
Fields: [
{FieldName:"CustomerName",
FieldType:"String",
Validations:[
{ValidationType:"Required"},
{ValidationType:"StringLength", Minimum:15, Maximum:50},
]},
...
{FieldName:"CustomerType",
FieldType:"Dropdown",
PossibleValues: ["Standard", "Valued", "Gold"],
DefaultValue: ["Standard"]
Validations:[
{ValidationType:"Required"},
{
ValidationType:"Custom",
ValidationClass:"MySystem.CustomerName.CustomValidations.CustomerStatus"
}
]},
...
]
};
With this kind of document to define your forms, you could easily add forms and validations which are customer specific.
You could easily add subforms using a fieldtype of SubForm or whatever.
You could define FieldTypes for all common types of fields like e-mail, phone numbers, address, etc.
namespace System.CustomerName.CustomValidations {
class CustomerStatus: IValidator {
private FormContext form;
private List<ValidationErrors> validationErrors;
CustomerStatus(FormContext fc) {
this.validationErrors = new List<ValidationErrors>();
this.form = fc;
}
public List<ValidationErrors> Validate() {
if (this.formContext.Fields["CustomerType"] == "Gold" && Int.Parse(this.form.Fields["OrderCount"]) < 10) {
this.validationErrors.Add(new ValidationError("A gold customer must have at least 10 orders"))
}
if (this.formContext.Fields["CustomerType"] == "Valued" && Int.Parse(this.form.Fields["OrderCount"]) < 5) {
this.validationErrors.Add(new ValidationError("A valued customer must have at least 5 orders"))
}
return this.validationErrors;
}
}
}
A record of a document with that definition could look like this:
{Type:"Record",
EntityType: "Customer",
Fields: [
{FieldName:"CustomerName", Value:"ABC Corp.",
{FieldName:"CustomerType", Value:"Gold",
...
]
};
Sure, this solution is a lot of work, but if/when realized it could be really easy to create/update/customize forms.
This is a common but (IMO) somewhat naive design approach. "Instead of solving the customer's problem, let's build a tool to let them solve their own problems!". But the reality is, that generally customers want YOU to solve their ACTUAL problems. So build things that solve their problems.
If you can architect it in a way that allows you to reuse some parts for different customers, fine. But that is generally what the frameworks have done for you already - work out the common features that applications need and make them available in neat packages.
We're currently migrating our ASP Intranet to .NET and we started to develop this Intranet in one ASP.NET website. This, however, raised some problems regarding Visual Studio (performance, compile-time, ...).
Because our Intranet basically exists of modules, we want to seperate our project in subprojects in Visual Studio (each module is a subproject).
This raises also some problems because the modules have references to each other.
Module X uses Module Y and vice versa... (circular dependencies).
What's the best way to develop such an Intranet?
I'll will give an example because it's difficult to explain.
We have a module to maintain our employees. Each employee has different documents (a contract, documents created by the employee, ...).
All documents inside our Intranet our maintained by a document module.
The employee-module needs to reference the document-module.
What if in the future I need to reference the employee-module in the document-module?
What's the best way to solve this?
It sounds to me like you have two problems.
First you need to break the business orientated functionality of the system down into cohesive parts; in terms of Object Orientated design there's a few principles which you should be using to guide your thinking:
Common Reuse Principle
Common Closure Principle
The idea is that things which are closely related, to the extent that 'if one needs to be changed, they all are likely to need to be changed'.
Single Responsibility Principle
Don't try to have a component do to much.
I think you also need to look at you dependency structure more closely - as soon as you start getting circular references it's probably a sign that you haven't broken the various "things" apart correctly. Maybe you need to understand the problem domain more? It's a common problem - well, not so much a problem as simply a part of designing complex systems.
Once you get this sorted out it will make the second part much easier: system architecture and design.
Luckily there's already a lot of existing material on plugins, try searching by tag, e.g:
https://stackoverflow.com/questions/tagged/plugins+.net
https://stackoverflow.com/questions/tagged/plugins+architecture
Edit:
Assets is defined in a different module than employees. But the Assets-class defines a property 'AssignedTo' which is of the type 'Employee'. I've been breaking my head how to disconnect these two
There two parts to this, and you might want to look at using both:
Using a Common Layer containing simple data structures that all parts of the system can share.
Using Interfaces.
Common Layer / POCO's
POCO stands for "Plain Old CLR Objects", the idea is that POCO's are a simple data structures that you can use for exchanging information between layers - or in your case between modules that need to remain loosely Coupled. POCO's don't contain any business logic. Treat them like you'd treat the String or DateTime types.
So rather than referencing each other, the Asset and Employee classes reference the POCO's.
The idea is to define these in a common assembly that the rest of your application / modules can reference. The assembly which defines these needs to be devoid of unwanted dependencies - which should be easy enough.
Interfaces
This is pretty much the same, but instead of referring to a concrete object (like a POCO) you refer to an interface. These interfaces would be defined in a similar fashion to the POCO's described above (common assembly, no dependencies).
You'd then use a Factory to go and load up the concrete object at runtime. This is basically Dependency Inversion.
So rather than referencing each other, the Asset and Employee classes reference the interfaces, and concrete implementations are instantiated at runtime.
This article might be of assistance for both of the options above: An Introduction to Dependency Inversion
Edit:
I've got the following method GetAsset( int assetID ); In this method, the property asset.AssignedTo (type IAssignable) is filled in. How can I assign this properly?
This depends on where the logic sits, and how you want to architect things.
If you have a Business Logic (BL) Layer - which is mainly a comprehensive Domain Model (DM) (of which both Asset and Employee were members), then it's likely Assets and Members would know about each other, and when you did a call to populate the Asset you'd probably get the appropriate Employee data as well. In this case the BL / DM is asking for the data - not isolated Asset and Member classes.
In this case your "modules" would be another layer that was built on top of the BL / DM described above.
I variation on this is that inside GetAsset() you only get asset data, and atsome point after that you get the employee data separately. No matter how loosely you couple things there is going to have to be some point at which you define the connection between Asset and Employee, even if it's just in data.
This suggests some sort of Register Pattern, a place where "connections" are defined, and anytime you deal with a type which is 'IAssignable' you know you need to check the register for any possible assignments.
I would look into creating interfaces for your plug-ins that way you will be able to add new modules, and as long as they follow the interface specifications your projects will be able to call them without explicitly knowing anything about them.
We use this to create plug-ins for our application. Each plugin in encapsulated in user control that implements a specific interface, then we add new modules whenever we want, and because they are user controls we can store the path to the control in the database, and use load control to load them, and we use the interface to manipulate them, the page that loads them doesn't need to know anything about what they do.
I've inherited a asp.net project and I'm finding that the code behind pages contain a lot of business logic.
I've decided that in most cases it's better to leave the working code in place than try and do a massive refactoring. However there are pages that perform functionality that could be re-used in command line utilities for batch processing. I'd like to focus my energies on these pages, refactoring out the business logic and referencing that in other utilities.
I am currently looking to refactor this particular page which has 6200 lines of code in the code behind. What I'm finding is it's very tedious work trying to locate the dependencies between the code behind and the page specific objects.
I'm wondering if anybody knows of a tool, a VS feature, or a method that would allow me to systematically locate and attack these dependencies? Something that will allow me to identify any area of the code that references ViewState, a textbox, panel, drop downlist, etc..., so I can move these references to method parameters and ultimately move this functionality out of the page class.
I would begin by examining any method that doesn't follow the Single Responsibility Principle and break them down so that they do. Once that's done you should have a handle on what the code does and you should be able to group the code more easily and move it into dedicated classes for those groups creating the necessary objects to use as you go. I find ReSharper is a very useful tool to help do all this. Ultimately you will always need to have a solid grasp of the fundamentals within the code before you can successfully refactor.
We've all been there at some point and you have my deepest sympathy but your willingness to attempt it at all means you're already heading in the right direction. Good Luck!
Wow first of all sorry to here that. Anyone who would put 6000 lines of code in code behind deserve to be smacked :)
Now I have done this kind of refactoring before. I would approach this in few steps:
(1) Create Logical Regions #Region and #EndRegion
Like - Save Methods , Load Methods or
(2) See if you can create physical business objects based on these regions in your business
layer
(3) Once you are done just refer all your code to appropriate class.
I understand you want some tool to make this all go away but I am afraid by doing this you will dig the hole dipper. Understanding the code and moving it method by method will give you better understanding.
One way I can immediately think is Compile then into Assemblies and Analyze the assembly using NDepend
http://www.ndepend.com/Features.aspx#DependencyCycle
(source: ndepend.com)
I was watching a tutorial on Rails and was very impressed that you could so easily create an editing system for a class just by defining it.
Can this be done in ASP.NET?
I know there are ORMs out there, but do they come with an editing system?
To explain what I mean by an editing system, consider a class for defining people
class Person
{
string First_Name;
string Last_Name
}
And then perhaps with one bold stroke something like this:
CreateEditAbleClass(Person)
You would get the functionality below in a browser:
http://www.yart.com.au/images/orm_editor.jpg
And this functionality would extend to all the UML definitions – inheritance, association, aggregation etc. In addition, there would be a simple way of adding customisable validation and so forth.
I currently use DataGrids and a lot of manual coding to achieve these results.
You can do it with reflection. Using reflection, you can enumerate over the members of a class, and therefore create a form to edit the members.
Creating the code for rendering the web form based on the members of the class is a bit more code then I'm willing to type out here, but if you look into reflection you should be able to come up with your own solution in a couple hours.
Sure. This is off the top of my head, but I believe you could connect your class to an ObjectDataSource component which would in turn connect to a DetailsView control. So it's a hair more work, but it would be pretty trivial to have a method that created the needed items on the fly and bound them together.
This is called "Scaffolding".
It really depends on what you are using for your data layer or ORM. Entityspaces, for example, comes with a scaffolding generator.
Absolutely! Scaffolding in Ruby is known as Dynamic Data in ASP.NET. Scott Hanselman speaks to Dynamic Data here.
There's a screen cast from Scott Hunter that shows it off here. It's of note that it's pretty new (still in beta).
You can for simple sites/purposes but it quickly breaks down when you want to do something more complex. Like what happens if you don't want certain fields to be visible, what happens if you have a relationship to a subset of a certain class etc.
Having been down this path before I'm guessing you came at the issue by realizing that:
You spend alot of time creating similar forms/lists etc for similar entities.
You want to minimize this time and are considering if your forms can be automatically generated.
Basically, if you want it to be done automatically then you'll end up creating an overcomplicated system that does half of what you want and actually takes longer to implement.
If however, you want to drastically cut the amount of time doing and maintaining writing repetitive gui code then then I suggest using a declarative style form builder and table builder (like the form builder in ROR).
This lets you quickly create forms/tables without repeating yourself any more than necessary and also gives you the flexibility that you need for complex scenarios.