2

Suppose I have two or more UserControl implementations with vastly different implementations but near identical code-behind. One strategy to avoid code duplication is as follows:

  1. Change each UserControl to inherit from a new abstract class, AwesomeUserControl
  2. Move all of the codebehind from each UserControl into AwesomeUserControl (AwesomeUserControl does not have an ascx file).
  3. Add abstract getters to AwesomeUserControl for any controls from the ascx file of the original UserControls.
  4. Implement these getters in each UserControl.

This strategy works extremely well and is easy to maintain. However, it also introduces stupid scaffolding code; every new implementation of AwesomeUserControl has a bunch of getters to hook AwesomeUserControl the UI elements inside of the new control. Any time I find myself using a strategy which requires copy-pasted scaffolding code, I worry that I am doing something wrong. Though it does have a nice effect of failing to compile if the UI elements are missing (as opposed to skipping the scaffolding code in favor of reflection and required naming).

Is this use of inheritance reasonable?

  • YMMV, but I have had horrible experiences with inheritance in UI forms. The first company I worked at had developed their most important product this way and it became such a tangled mess that hardly anyone could add features to it anymore... Is there a way you can split of the common code into a shared class and use composition? – Stefan Billiet May 22 '14 at 7:01
1

Vastly different implementations? Sounds like a bad candidate for a common abstract parent class, don't you think?

Otherwise, you have to be more precise than AwesomeUserControl. What are the exact controls which share the same logic? What logic is shared?

As an illustration, here's a copy-paste from an answer I wrote a few days ago:

  • Either two classes are related (for example both Cat and Dog can be fed, and it takes the same steps to feed them both, except the food which will change), in which case, create an inheritance (in my example, a parent class Pet),

  • Or two classes are unrelated, and just rely on the same method. For example, WebRequest class may rely on GetSlug¹ to find the slug of the current request; Customer may also rely on GetSlug to normalize the name of the customer for further search purposes. However, WebRequest and Customer are totally unrelated, and it makes no sense to create a common object for those classes.

    Here, the solution would be to call a common method from those two classes, by instantiating the third class containing this method. For example, both RequestUri and CustomerName may become objects implementing ISlug interface.

  • Perhaps my wording is unclear. It would be more precise to say vastly different aspx and near-identical aspx.cs. – Brian Apr 22 '14 at 1:57
  • @Brian: my point is, are those controls logically related? – Arseni Mourzenko Apr 22 '14 at 10:12
  • 1
    Yes. They look different, but they behave identically and are used for the same purpose. A better way to accomplish the same task would be to just use the same control, but different CSS. However, usually the different UIs are modified very much independently from one another, so this tends to be more work to maintain. In short, there is no expectation that the changing one UI means changing another UI, but changing the codebehind is expected to impact all controls. – Brian Apr 22 '14 at 13:25
  • 1
    @Brian: Then yes, creating a parent class looks like a good solution. – Arseni Mourzenko Apr 22 '14 at 15:11
1

I would have to say that it depends vastly on the two classes.

If you have two classes that share many of the same methods AND share many of the same properties and fields then I would create a parent class. Inheritance is probably your best solution here.

An interface is nice, but I don't think it will help you with what you want, which I believe you are looking for code reduction.

I do not agree with the ISlug Interface example from MainMa, but again, that depends on the implementation of the objects. Interfaces are great, but you don't have to make one just because two classes share the same method names and parameters.

If you post a little bit more about what your two buttons do, and maybe just the functions and fields/properties they share, It would be a little more enlightening to the situation.

  • Example controls would be a date picker, a smart download button, a next/previous button containing a datapager. Basically, controls that may end up looking vastly different but will behave mostly the same. Of course, it's hard to offer an example which is both trivial and fails to be amenable to the simpler solution of using only one control but two css classes. – Brian Apr 22 '14 at 2:07
  • @Brian Unless you need a class to inherit more than one base class, or you intend to do polymorphic programming, interfaces are unreasonable. Remember that a base class of a base class is inherited. I would suggest that you give it a shot, if you can reduce the code that you have to manage, by creating a base class without over complicating things, I would suggest so. Also I would like to remark on that interfaces are not always the best nor the only way to implement polymorphic programming, just to be clear. Anyways, give it a shot. Let me know if you have trouble, I can help you further. :) – Ruina Apr 22 '14 at 3:30
  • @Brain You can send me a private message if you want with your code if your having with the design. I would be more than happy to help. – Ruina Apr 22 '14 at 3:35
-1

This strategy works extremely well and is easy to maintain. However, it also introduces stupid scaffolding code; every new implementation of AwesomeUserControl has a bunch of getters to hook

Access controls directly. On the abstract class:

#Region "WebControls - Objects must be on derived aspx and deleted from .asx.designer"
  Protected WithEvents SomeDiv As Global.System.Web.UI.HtmlControls.HtmlGenericControl
  Protected WithEvents SomeLabel As Global.System.Web.UI.WebControls.Label
  Protected WithEvents SomeLinkButton As Global.System.Web.UI.WebControls.LinkButton
  ...
#End Region
  • 1
    How does this address the points the raised in the question? – GlenH7 Jan 14 '15 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.