How to design these classes?

Hello all

I currently have quite a large project that contains several classes that relate to various objects in a database. For example, the Orders class contains methods that have anything to do with orders. At the moment I think I've designed it in a very simple way, for example:

public class Orders
{
public Orders()
{
}

public int CreateOrder(int storeId)
{
// Code to create an order and return the ID.
}

public OleDbDataReader GetOrder(int orderId)
{
// Code to return the order record.
}
}

Basically, to use any of the methods, I first create an instance of the Orders class, but this doesn't seem like a very good way of doing things. Would it be better to have static methods for things like CreateOrder() and non-static methods for anything that relates to a specific order ID For example:

public class Orders
{
private int _orderId;

public Orders(int orderId)
{
_orderId = orderId;
}

public static int CreateOrder(int storeId)
{
// Code to create an order and return the ID.
}

public OleDbDataReader GetOrder(int orderId)
{
// Code to return the order record.
}
}

Thanks for any help.

Regards

Tom


Answer this question

How to design these classes?

  • Kevin_B

    What venkat suggests is actually the best way to do thing (IMO). I have recently just completed a huge order system that holds approx 80 tables and is used concurrently by about 100 users. I more or less followed the same pattern and I'm now reaping the rewards. It's a bit more work at the beginning but it really does make a difference once you finish your system.

    I suggest you have a look at CSLA.Net http://www.lhotka.net/Area.aspx id=3 by Rockford Lhotka, its quite an interesting way of doing things and there are lots of active users of the framework. Also, there are CodeSmith templates for this which will write all your code for you!! While I'm not overly keen on the 'class in charge' design, it definitely works and there are some excellent techniques that you will use in all your projects.

    To address your specific question, static methods will probably be OK because you are not interested in state at any point - you are simply returning an object that implements IDataReader. If you had designed an 'Order' entity to represent an order, then this is where you would have a ctor.

    Here is some code from my 'CatalogueSystem' that allows me to query for products to order. This system provides a layer of abstractation between my Client GUI and the DAL. It performs some argument validation to ensure we don't take a fruitless trip to the DAL. A static method is fine here because I wouldn't want to create an instance of CatalogueSystem at any point, I just want to get at the data the method provides access to. A call to this method looks like this from my GUI, which I think is very clean & self describing.

    ObjectSet searchResults = CatalogueSystem.SearchCatalogue(SearchMode.ByArtist, "Radiohead", 1)

    /// <summary>
    /// Retrieves a ObjectSet containing all the items that fullfill a search criteria.
    /// </summary>
    /// <param name="searchType">Specifies the type of search to be performed.</param>
    /// <param name="searchText">The text to search for.</param>
    /// <param name="searchRange">Type type of catalogue data to search (active / deleted / both)</param>
    /// <retvalue>A strongly typed collection of SearchItem objects containing all the data on the catalogue
    /// information system that fulfills the search criteria.</retvalue>
    /// <exception cref="System.Exception">
    /// The searchType is not within the correct range, or searchText is empty.
    /// </exception>
    public static ObjectSet SearchCatalogue(SearchMode searchType, String searchText, short searchRange)
    {
    //
    // Check preconditions
    //
    ApplicationAssert.CheckCondition(searchText != null && searchText.Length > 0, "searchText is required", ApplicationAssert.LineNumber);
    searchText = (new StringBuilder(searchText)).Replace("\"", "\"\"").ToString();

    ObjectSet results = null;

    // Attempt the search
    switch (searchType)
    {
    case SearchMode.ByArtist:
    results = DataManager.CatalogueData.SearchByArtist(searchText, searchRange);
    break;
    case SearchMode.ByTitle:
    results = DataManager.CatalogueData.SearchByTitle(searchText, searchRange);
    break;
    case SearchMode.ByCatalogueNumber:
    results = DataManager.CatalogueData.SearchByCatalogue(searchText, searchRange);
    break;
    }

    return results;

    }


  • MyName Dot

    Of course that you can use static methods, but your aproach is not perfect. You should create properties that holds data for an Order. Also if you have a method that creates Order, it is better that method returns instance of created Order. Order type should be a return type for GetOrder method also. For Delete you can have two methods, static that accepts OrderId parameter and delete order with that id, and non static that have no paramaters and delete that instance.
    public bool Delete()
    {
    Delete(this.OrderId);
    }
    public static bool Delete(int orderId)
    {
    //call some datalayer function for executing commands and give that command an orderId argument
    }
    For Update you will have only non static method.



  • Thomas.Goddard

    Thank you Dylan, I think that answers my question. :) I'm very keen on doing things the way you and venkat have described, it seems a lot cleaner, it's just a lot of work for me to do. Worth it though.

    Regards

    Tom

  • Juan Castillo

    I see, thank you. :) I do like that method of doing things, it would make things much nicer to read, so I will give it some thought.

    However, back to my original question of how to define the methods in each class. Is it ok to define them all as static, as Mark said, since I'm just grouping them all together, or would a more object-oriented method be better

  • MrSock

    If you're just using classes to group methods, as you seem to be, then all the methods can be static.

  • Humpty

    Fine,

    On the first hand, sorry for not being too clear on taking u in this regards. When i meant BusinessEntities for respective tables, the business entity may contain information about more than one table also!

    For example,

    There are three tables Orders, Customers and Transactions.

    Lets call the bizEntity for Transaction as TxnEntity. Lets assume 3 fields in Transaction table, one of them being ORDER_TAKEN_BY which takes value of CustomerID.

    However the front-end may require to display the Customer Name in place of Customer ID.

    So in this place, it is required to go for a join and eventually it is evident that the bizEntity should have provision for supporting the property CustomerName.

    So along with creating property for OrderTakenBy (which may be an int) there could be a property OrderTakenByCustomerName (a string)

    This way u can solve join query problems.

    Regarding the complexity, yes, this may be a complicated process to start with, however this could be easier for you in case of any modifications. (Anyway I agree with u that this design may not be best suited for systems already up and running)

    And lastly, if there r 10 tables there need not be 10 entities. Some of the entities might be clubbed together depending on ur configuration and db design.

    :)



  • Mark Macumber

    Hi Venkat

    Unfortunately, that approach would complicate things way too much for me. For a start it would mean a major overhall of the code, but I also have about 100 tables in the database, and I'm not sure how I'd return data from a query that joins to several tables.

    Thanks for the suggesstion though. :)

    Regards

    Tom


  • Abhishek Chadha

    Tom,

    Jus chk whether this approach holds good. What you can do is create Business Entities for the back end tables. i.e. For Orders tables, create an Order entity in the frontend. For Transaction, create something like TransactionEntity.

    Let these business entities be a seperate components.

    Then, to access the database, you can have another (seperate) component to access the data layer exclusively. (The DALC layer)

    The Business entity (the component that holds all the classes that corresponds to the back end tables) will be visible through out the layers viz. from the front-end user interface till the Dalc Layer.

    The Dalc Layer contains methods to interact with the database.

    The Front end (or any middleware) can give the calls to the Dalc layer.

    Hope I am clear.

    Get back on any clarification. Let me know if u need any code samples.

    Cheers,
    Venkat


  • redshock

    Really Does this not use up more memory (as some classes are rather big)

  • How to design these classes?