简体   繁体   中英

What's wrong with my classes?

Submitted these two classes (along with business logic and data access logic) for code review. The reviewer laughed looking at the code and advised me to re-do the classes. He told me to do some research and would not give me any clues. I couldn't find anything wrong. It looks little awkward that "submenu" is base class instead of menu. But my requirement is like that . . . menu is only of two levels (sub-sub-menu will never exist). What's so funny about them? Would be grateful if somebody shows me the path to improve these classes.

[Serializable]
public class Menu: SubMenu
{
    private List<SubMenu> _subMenu;
    public List<SubMenu> SubMenu
    {
        get
        {
            if (_subMenu == null)
                _subMenu = new List<SubMenu>();
            return _subMenu;
        }
        set
        {
            _subMenu = value;
        }
    }
}

[Serializable]
public class SubMenu
{
    public int ID { get; set; }
    public string MenuText { get; set; }
    public string MenuURL { get; set; }
    public string ImageURL { get; set; }
}

The biggest issue here is the professionalism of whoever did your review - you should ask that they be more constructive and helpful and if they still insist in being so rude that I'd take it to a manager.


That said, my guess at what they saw in your design was the fact that you are using inheritance at all. Do you need inheritance here? It seems that you would be better served by having a Menu class which contains a list of SubMenus with no parent-child relationship or perhaps just a single MenuItem object which can contain a list of itself.

I'd prefer the second approach actually, something like this maybe:

[Serializable] 
public class MenuItem
{ 
    public MenuItem()
    {
        MenuItems = new List<MenuItem>();
    }

    public int ID { get; set; } 
    public string MenuText { get; set; } 
    public string MenuURL { get; set; } 
    public string ImageURL { get; set; } 

    // I'm not bothering with the code to protect access to the list
    // in this example but you might want that too...
    public List<MenuItem> MenuItems { get; set; }
} 

The overall construction of your objects is good, such as the lazy instantiation, although as other answers suggest, I think your inheritance is a bit miss-leading; but that isn't a problem!

Here are a few suggestions; Even though only 1 level deep is required, I would suggest implementing the availability of more levels, as it isn't overly difficult, and could save you re-factoring things in the future. Additionally we could add a couple of constructors to the object to make it easier when creating a new menu item.

I've created my concept of a menu item, which is purely a suggestion, but hopefully it helps. Here are some things to note.

  1. I've removed the base object
  2. The menu item now longer uses lazy instantiation, but creates a list upon construction
  3. There are new constructors
  4. The menu items can be infinite levels deep.

and here's how it looks:

[Serializable]
public class MenuItem
{
    public int Id { get; set; }
    public string MenuText { get; set; }
    public string MenuUrl { get; set; }
    public string ImageUrl { get; set; }

    public List<MenuItem> Children { get; set; }

    public MenuItem(int id, string text, string url)
        : this(id, text, url, String.Empty)
    {
    }

    public MenuItem(int id, string text, string url, string imageUrl)
    {
        this.Id = id;
        this.MenuText = text;
        this.MenuUrl = url;
        this.ImageUrl = imageUrl;

        this.Children = new List<MenuItem>();
    }
}

i agree with the above commentators. for your reviewer to just laugh and offer no constructive advice is both rude and counterproductive. my answer would be ' go back and get professional constructive advice ' from the reviewer first. If that is not forthcoming, then I'm afraid it looks like the reviewer is driven by ego, rather than stewardship and the principals of guidance and education.

Considering your requirements, the only thing I find wrong is a naming issue:

public List<SubMenu> SubMenu

That's a collection, it should be plural. But seriously, that's nothing to laugh about..

Now if you go back to your ******e reviewer, get your arguments ready:

  • Inheritance PLUS a Collection is necessary because a Menu is itself a SubMenu since a Menu has a Text/Url/Image/ID, and it has a collection of submenus that go belows him.

  • Explain the requirement where SubMenu is a base class for Menu (which is really not so straighforward).

My best guess is that it all looked slightly goofy and he gave no more than a glance at it.

Submitted these two classes (along with business logic and data access logic) for code review. The reviewer laughed looking at the code and advised me to re-do the classes. He told me to do some research and would not give me any clues.

Bad review, there really is no point in having you look it up, especially if you really don't see anything wrong in your own code.

I couldn't find anything wrong. It looks little awkward that "submenu" is base class instead of menu. But my requirement is like that... menu is only of two levels (sub-sub-menu will never exist).

I don't find your implementation funny, but the naive though that there is such a thing like "never" is sort of funny. If I had a penny for every time someone said something would never happen, and it eventually did happen, I'd be at least one 15 pence richer by now.

If your requirement is that a menu only has two levels, don't build code to extend upon that requirement. However, if you have an option to open up your code to future extension very easily, then why not do it? There's no cost, just benefit. And in your case, I think "opening up to future extension" is indeed quite simple.

What's so funny about them? Would be grateful if somebody shows me the path to improve these classes.

It's not necessarily funny, or wrong. I'd do it differently though: if a menu can contain a menu, wouldn't that be composition? And if so, what is the difference between a menu and a submenu? A submenu is a menu that happens to have a parent, but should it care? Should it know? Does it actually have any different behaviour than the menu itself?

class Menu
  +addSubmenu( Menu menu ) : Menu
  +addItem( Item item ) : Menu

That's what my attempt would look like, probably.

Reviewer not helpful or professional. Whilst being courteous you need to be clear that such a review is pointless. It's the responsibility of those who have knowledge/experience to share when asked.

I think you need to look at renaming types /properties eg the answers suggesting "MenuItem" as the base class name are clearer to follow.

Also the confusion between inheriting from SubMenu (misleading since you usually inherit from a base class or a super class depending on the terminology you prefer and the thing doing the inheriting is a sub class) and having a property also called SubMenu and that property represents a set rather than a single instance.

Look at a menu implementation eg in winforms - they're easier to follow

I'm not sure if I'm correct with following statement (and please do correct me if I am wrong) but if a class inherits from a base class, should the derived class hold a list of items of its base class? And in what case could that be useful (I can't think of any right now). If i think of, for example, 'Horse' and 'Animal': should the class Horse hold a list of Animals? Sounds a bit strange..

It seems that you have a menu which can contain two types of items

1) A 'Simple menu item' (Id, Text, url, image)
2) Another menu (sub menu)

I know that you only want to go one level deep but it may actually be simpler to re-use a generalized solution.

The Composite Design Pattern ( http://en.wikipedia.org/wiki/Composite_pattern ) seems to be a good fit.

hth,
Alan.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM