Design Pattern Advice: Rule checker - asp.net

I sell products throgh my website. Recently we've been given a list of rules that need to be checked against each order, to make sure it's not fraudulent. So this list of rules/fraud indicators will change and grow so I want to make sure it's easily maintainable and really solid.
I'm thinking I have an abstract class rule that each of the rules implements.
abstract class Rule
{
public string Message;
public bool Success;
public void CheckOrder(OrderItem currentOrder);
}
class FakeCreditCardNumberRule : Rule
{
public string Message = "Fake CC Number Rule";
public void CheckOrder(OrderItem currentOrder)
{
currentOrder.CreditCardNumber = "1234-5678-9012-3456";
Success = false;
}
}
class ReallyLargeOrderRule : Rule
{
public string Message = "Really Large Order Rule";
public void CheckOrder(OrderItem currentOrder)
{
currentOrder.ItemsOrder.Count > 100;
Success = false;
}
}
Then I'm thinking of having a class that accepts an Order object in it's costructor and checks though the list of rules. Something like:
class FraudChecker
{
List<Rule> rules;
public FraudChecker(OrderItem currentOrder)
{
foreach(var rule in rules)
{
rule.CheckOrder(currentOrder);
}
}
}
So I was trying to think of the best place/best way to populate the FraudChecker
.Rules list and started thinking there might be some nice design pattern that does something like what I'm doing.
Has anyone seen a design pattern I should use here? Or can anyone think of a good place to populate this list?
-Evan

Specification Pattern
I've been dealing with a very similar issue.
I've found the Specification Pattern to be particularly useful.
For me the main benefits of the pattern is the way it incorporates chaining.
The link above provides a basic overview, and the related links in the article are useful too. After, if you do some more searching you'll find more detailed examples.

You have already used the Startegy pattern... I believe a factory pattern can solve your problem.
Link

I would probably go with my own implementation of enum. I would create a class like this:
public sealed class Rules
{
public static readonly Rule FakeCreditCardNumberRule = new FakeCreditCardNumberRule ();
public static readonly Rule ReallyLargeOrderRule = new ReallyLargeOrderRule ();
//here I would write more
private static readonly List<Rule> _all = List<Rule> { FakeCreditCardNumberRule, ReallyLargeOrderRule };
//every time you add new rule to the class you have to add it to the _all list also
public static IEnumerable<Rule> All
{
get
{
return _all;
}
}
public static FraudChecker(OrderItem currentOrder)
{
foreach(var rule in All)
{
rule.CheckOrder(currentOrder);
}
}
}
and then you can use it like this:
Rules.FraudChecker(currentOrder);
or
Rules.FakeCreditCardNumberRule.CheckOrder(currentOrder);
You can add every new rule to the Rules class. You can also create new methods in it that will process only part of the Rules and so on.

Related

LSP - Liskov Substitution Principle particular case

i'am not sure about special case of LSP.
Actually child should extend implementation of parent and not change it.
For me means extension, that i add new lines in child implementation to parent
implementation within child class.
But what about, when i completely override parent-implementation and it provides
result too?
Parent is:
public class Calculator {
public void computeProfit(){
int profit = 2+2;
}
}
Child is:
public class SpecialCalculator extends Calculator {
#Override
public void computeProfit(){
//overriding completely parent-implementation
int profit = Math.pow(2) * 5;
}
}
has LSP still been preserved?
TL;DR; In you example LSP is preserved.
IMO the thing with SOLID principles it that it is a mnemonic for dynamic polymorphism so the end goal for your code is to enable something like this
public void SomeBusinessLogic(Calculator calc) {
calc.computeProfit() // SpecialCalculator might go here as well
}
Your code is perfectly fit for this.
This however would violate LSP
public class SpecialCalculator extends Calculator {
public void computeProfitClevrly(){
//overriding completely parent-implementation
int profit = Math.pow(2) * 5;
}
}
because now you'll have to do something like
public void SomeBusinessLogic(Calculator calc) {
if (calc is SpecialCalculator)
calc.computeProfitCleverly() // SpecialCalculator might go here as well
}
P.S. There are some more subtle cases of LSP violation. I.e. when base class is ImmutablePoint and a child class is a point that might be mutated.

Finding all Classes beloning to a superclass using Java 7

I'm looking for a way in java to find all classes that belongs to a certain superclass, and within that class refer to a static string with a known name (using reflection?);
public class Bar
extends ObjectInstance
{
public final static String Name = "Foo";
// more
}
From the example; there are n-occurences of classes that extend from ObjectInstance, and from all, i need the value of Name. The classes i am refering to are generated so i know for sure that there is a Name element that i can refer to, but i have no access to the generation sourcedata.
Perhaps the same question as How do you find all subclasses of a given class in Java?
This backs up my initial feeling that this can only be done like IDEs do it: by scanning everything down the tree, building your relationships as you go.
No Way.
One failing solution:
publc abstract class ObjectInstance {
public abstring String name();
private static Map<String, Class<? extends ObjectInstance> klasses =
new HashMap<>();
protected ObjectInstance() {
classes.put(name(), getClass());
}
Only collects instantiated classes! So fails.
With the idea to have the name provided by a function with return "foo";.
Collecting the class.
There are two unsatisfactory solutions:
The other way around: use the name as a factory pattern:
enum Name {
FOO(Bar.class),
BAZ(Baz.class),
QUX(Qux.class),
BAR(Foo.class);
public final Class<ObjectInstance> klass;
private Name(Class<ObjectInstance> klass) {
this.klass = klass;
}
}
Maybe as factory to create instances too.
Using a class annotation, and have a compile time scanning:
#ObjectInstanceName("foo")
public class Bar extends ObjectInstance {
}
How to apply this to your case: experiment.
There would be a more fitting solution of using your own ClassLoader, but that is far too over-engineered.

Factory pattern to "set" product in addition to "get" product?

I am new to design patterns. I am looking for a pattern similar to the factory pattern but that will also let me "set" the product. Something like this:
class VehicleFactory
{
IVehicle static GetVehicle();
void static SetVehicle(IVehicle vehicle);
}
Is there any known pattern similar to this? Thank you.
EDIT: I am looking to store "POCO" objects in the Session object and use a class to set/ get them. I may want to switch persistance to ViewState/ database in the future. This is what I have:
// object to persist in Session.
class Vehicle
{
string Make { get; set; }
string Model { get; set; }
}
// class to set/ get object from Session.
// Please see VehicleFactory above.
Factory pattern is a creational design pattern with encapsulates the creation of a complex object and isolates the creation process from your business logic.
Here it looks like you want a cache to store and manage the Vehicle instances. I would recommend that you call this class a VehicleCache rather than Factory and implement like a cache.
Firstly you should consider having and identifier for the Vehicle object like a vehicleId. I would also recommend that you implement it as an entity object as described in Domain Driven Design.
Then you can implement your cache like this -
public class VehicleCache
{
public void Add(IVehicle instanceToAdd)
{
// Store instance in session object
}
public IVehicle Get(string id)
{
// search and return vehicle from cache
}
// more methods and indexer if required
}
Here are some links that explain how you can implement such cache for your application in a thread safe fashion -
https://blogs.infosupport.com/blogs/frankb/archive/2008/12/31/Implementing-a-Thread-Safe-cache-using-the-Parallel-Extensions.aspx
http://www.objectreference.net/post/Implementing-Generic-Caching.aspx
Like Unmesh says, the name is kind of misleading.
You simply want to cache IVehicle object.
IVehicleCache
{
IVehicle GetVehicle();
void SetVehicle(IVehicle vehicle);
}
// Implementation for http session
public class HttpSessionVehicleCache : IVehicleCache
{
public IVehicle GetVehicle()
{
return (IVehicle)HttpContext.Current.Session["Vehicle"];
}
void SetVehicle(IVehicle vehicle)
{
HttpContext.Current.Session["Vehicle"] = vehicle;
}
}

static constants return instance of specific class in Flex?

So here's what I mean.
Let's say I have a class ErrorMessages which holds all my error messages as static constants. So I could access them like ErrorMessages.PASSWORD_INVALID or ErrorMessage.PASSWORD_TOO_SHORT. I want to know if it is possible to have separate classes that hold subset of these constants and access them like ErrorMessages.PASSWORD.INVALID or ErrorMessages.PASSWORD.TOO_SHORT, etc.
This way I can more structured static structure and makes it much easier to use autocomplete.
I tried few different ways and couldn't figure out if this was possible..
Declare them as const Objects in the static class - you won't get them in auto complete though.
public class ErrorMessages
{
public static const PASSWORD:Object = {
INVALID:"invalid password",
TOO_SHORT:"minimum 6 chars required",
TOO_LONG:"100 chars: r u sure?"
};
public static const FILE:Object = {
NOT_FOUND:"No such file",
READ_ONLY:"it is readonly",
SOMETHING_ELSE:"something else"
};
}
trace(ErrorMessages.PASSWORD.INVALID);
If auto complete is important, create a dedicated com.domain.errors package and declare different classes for different categories of errors (like PASSWORD, FILE etc) within that package. Now declare public static constants inside those classes as appropriate.
or if you want to keep a single class, you can define classes, inside your Error class. You might would like to have those text coming from properties file. So, you can make use of resourceManager instance and get the text from specific resource bundle.
--
http://riageeks.com
Here's what I end up doing
package com.domain.data.type {
public class ErrorMessages {
public static function get PASSWORD:PasswordErrorMessages { return new PasswordErrorMessages(); }
}
}
class PasswordErrorMessages {
public function get INVALID():String { return "invalid password"; }
}
This way I can get the behavior I wanted: ErrorMessages.PASSWORD.INVALID with autocomplete. It's not as clean as I'd like it to be.. but I guess this will do.

ASP.NET - Avoid hardcoding paths

I'm looking for a best practice solution that aims to reduce the amount of URLs that are hard-coded in an ASP.NET application.
For example, when viewing a product details screen, performing an edit on these details, and then submitting the changes, the user is redirected back to the product listing screen. Instead of coding the following:
Response.Redirect("~/products/list.aspx?category=books");
I would like to have a solution in place that allows me to do something like this:
Pages.GotoProductList("books");
where Pages is a member of the common base class.
I'm just spit-balling here, and would love to hear any other way in which anyone has managed their application redirects.
EDIT
I ended up creating the following solution: I already had a common base class, to which I added a Pages enum (thanks Mark), with each item having a System.ComponentModel.DescriptionAttribute attribute containing the page's URL:
public enum Pages
{
[Description("~/secure/default.aspx")]
Landing,
[Description("~/secure/modelling/default.aspx")]
ModellingHome,
[Description("~/secure/reports/default.aspx")]
ReportsHome,
[Description("~/error.aspx")]
Error
}
Then I created a few overloaded methods to handle different scenarios. I used reflection to get the URL of the page through it's Description attribute, and I pass query-string parameters as an anonymous type (also using reflection to add each property as a query-string parameter):
private string GetEnumDescription(Enum value)
{
Type type = value.GetType();
string name = Enum.GetName(type, value);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
return attr.Description;
}
}
return null;
}
protected string GetPageUrl(Enums.Pages target, object variables)
{
var sb = new StringBuilder();
sb.Append(UrlHelper.ResolveUrl(Helper.GetEnumDescription(target)));
if (variables != null)
{
sb.Append("?");
var properties = (variables.GetType()).GetProperties();
foreach (var property in properties)
sb.Append(string.Format("{0}={1}&", property.Name, property.GetValue(variables, null)));
}
return sb.ToString();
}
protected void GotoPage(Enums.Pages target, object variables, bool useTransfer)
{
if(useTransfer)
HttpContext.Current.Server.Transfer(GetPageUrl(target, variables));
else
HttpContext.Current.Response.Redirect(GetPageUrl(target, variables));
}
A typical call would then look like so:
GotoPage(Enums.Pages.Landing, new {id = 12, category = "books"});
Comments?
I'd suggest that you derive your own class ("MyPageClass") from the Page class and include this method there:
public class MyPageClass : Page
{
private const string productListPagePath = "~/products/list.aspx?category=";
protected void GotoProductList(string category)
{
Response.Redirect(productListPagePath + category);
}
}
Then, in your codebehind, make sure that your page derives from this class:
public partial class Default : MyPageClass
{
...
}
within that, you can redirect just by using:
GotoProductList("Books");
Now, this is a bit limited as is since you'll undoubtedly have a variety of other pages like the ProductList page. You could give each one of them its own method in your page class but this is kind of grody and not smoothly extensible.
I solve a problem kind of like this by keeping a db table with a page name/file name mapping in it (I'm calling external, dynamically added HTML files, not ASPX files so my needs are a bit different but I think the principles apply). Your call would then use either a string or, better yet, an enum to redirect:
protected void GoToPage(PageTypeEnum pgType, string category)
{
//Get the enum-to-page mapping from a table or a dictionary object stored in the Application space on startup
Response.Redirect(GetPageString(pgType) + category); // *something* like this
}
From your page your call would be: GoToPage(enumProductList, "Books");
The nice thing is that the call is to a function defined in an ancestor class (no need to pass around or create manager objects) and the path is pretty obvious (intellisense will limit your ranges if you use an enum).
Good luck!
You have a wealth of options availible, and they all start with creating a mapping dictionary, whereas you can reference a keyword to a hard URL. Whether you chose to store it in a configuration file or database lookup table, your options are endless.
You have a huge number of options available here. Database table or XML file are probably the most commonly used examples.
// Please note i have not included any error handling code.
public class RoutingHelper
{
private NameValueCollecton routes;
private void LoadRoutes()
{
//Get your routes from db or config file
routes = /* what ever your source is*/
}
public void RedirectToSection(string section)
{
if(routes == null) LoadRoutes();
Response.Redirect(routes[section]);
}
}
This is just sample code, and it can be implemented any way you wish. The main question you need to think about is where you want to store the mappings. A simple xml file could do it:
`<mappings>
<map name="Books" value="/products.aspx/section=books"/>
...
</mappings>`
and then just load that into your routes collection.
public class BasePage : Page
{
public virtual string GetVirtualUrl()
{
throw new NotImplementedException();
}
public void PageRedirect<T>() where T : BasePage, new()
{
T page = new T();
Response.Redirect(page.GetVirtualUrl());
}
}
public partial class SomePage1 : BasePage
{
protected void Page_Load()
{
// Redirect to SomePage2.aspx
PageRedirect<SomePage2>();
}
}
public partial class SomePage2 : BasePage
{
public override string GetVirtualUrl()
{
return "~/Folder/SomePage2.aspx";
}
}

Resources