3

Over the past several months I have learned a lot in software design and practices across several languages and frameworks. To me, the most attractive and useful designs patterns are those that follow an object-oriented approach. Particularly I am drawn to an approach that promotes reusability, modulariy, understanding (reusing understood code), and more.

The general approach that I find myself using often is one which encapsulates program functionality into separate components with minimal coupling. When I visualize this design I often imagine a hierarchical structure of objects and sub-objects, where each is only aware of its own interface and those of its members. As I understand, this last part is essential to achieving the sought after characteristics I mention above.

Keeping this in mind, for the various projects I have been working on over the past couple of months I have found myself hitting design roadblocks. How exactly do I define an object such that it is able to fulfill its intended functionality within my application while also having a simple and intuitive interface? More specifically (and perhaps in simpler words), how do I implement needed functionality in an object, which also isn't too specific for common applications?

I'll describe a case in which I am facing this issue:

Working with the Java Server Faces (JSF) framework to create a web application, and so my design is centered around page templating. This entails writing XHTML templates that can be reused whenever needed.

I want to create a header template that contains all the header markup I will use across my entire website. Here's an example:

<!-- header.xhtml -->

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html />

<html  xmlns="http://www.w3.org/1999/xhtml"    
       xmlns:ui="http://java.sun.com/jsf/facelets">

<body>
    <div class="title">My Website</div>
</body>

</html>

Now, if I want add some flexibility to serve different header titles, I can add an insert tag like so:

<body>
    <div class="title">
        <ui:insert name="insertTitle">My Website</ui:insert>
    </div>
</body>

The details are not important for this discussion, but the insert tag lets pages using this template add a custom title in place of the default My Website.

This added functionality to the template seems appropriate and could definitely receive common use.

What if, however, I have a single page on my website that needs a button located in the header? Do I add another insert tag for this very purpose, even though it has single usage? In all other uses of the template this functionality is ignored and so could be considered code waste.

This issue of mine doesn't just present itself when working with html templating but for any approach that involves reusable sub-component design. Any tips or design insight for choosing functionality would be greatly appreciated.

  • 2
    Tip #1: Don't use JSF. – Robert Harvey Jul 26 '16 at 22:25
  • It sounds like you're asking how to design an API. This presentation is somewhat Java-oriented, but still broadly applicable. – Kevin Krumwiede Jul 27 '16 at 1:16
  • @RobertHarvey I am relatively new to programming, and especially web development. I have been reading up on criticisms of JSF and server-side state management in general and understand where they are coming from. However, having learned web development using modern online guides and frameworks, I've already been operating under mindset of using asynchronous JavaScript for dynamic pages whenever possible. I had gone into using JSF under the assumption that it was a tool to more dynamically generate HTML for INITIAL requests. Should I just be writing pure servlets or use a different framework? – Dan Jul 27 '16 at 2:09
3

I might get down-voted for telling you not to use OOP, but: don't use OOP.

I will try to explain why without running out of space :)


Particularly I am drawn to an approach that promotes reusability, modularity, understanding (reusing understood code), and more.

Of course you are! That's what all software engineers strive towards. It's the holy grail. No one is intentionally trying to make anti-modular code. And furthermore, no language can make all the code you write fit these criteria. There is no magic-bullet general-purpose programming language.

The general approach that I find myself using often is one which encapsulates program functionality into separate components with minimal coupling.

That's the goal, not an approach. How do you decide on what components to create? How do you model them and their relationships? What are the interfaces? What's the level of abstraction? These are the important decisions.

When I visualize this design I often imagine a hierarchical structure of objects and sub-objects, where each is only aware of its own interface and those of its members. As I understand, this last part is essential to achieving the sought after characteristics I mention above.

Untrue.

Firstly, hierarchies, while pleasant to imagine in our heads, are rarely so straightforward. This is true in any field. Have you ever tried studying the classification of living organisms? It's a mess. Unfortunately, building correct, semantically meaningful ontologies is a near-impossible task for humans. This has been proven time and time again.

The problem is compounded when the members of the ontologies themselves are ever-changing, as is the case in software. Tomorrow you might have to add a new component, or update an existing one. Will your hierarchy still hold true?

Second, you are compounding the two ideas of inheritance and subytping into the one word hierarchy. Inheritance is simply a way to write programs (i.e. save keystrokes); it has no semantic meaning. Subtyping is an intrinsic relationship that exists between some types (classes) in a language. The two concepts are entirely separable. One may create a system of inheritance in which the sublcass does not automatically become a subtype of the super class Similarly, one may make a language where some types are automatically determined to be subtypes of others; this is called structural subtyping.

Hierarchies are not essential to modular programming. What is important to modular programming, is, well, modules -- components with well-defined interfaces (the interface is itself some form of type). There need be no hierarchy among the modules, and this is generally the best approach for small projects. When projects get larger, you probably need some form of reuse; the formal term for this is polymorphism. Subtyping is but one form of polymorphism; parametric polymorphism is an alternative approach (the two may of course be used together).

Your example

Let's go over your specific example, which aptly demonstrates the some of the shortcomings of inheritance. Many would not consider writing HTML templates true programming, but I'm not going to argue definitions; it's significantly different from writing Java code, but they both share the weakness of inheritance.

I actually have hands-on experience in this particular domain. At my company we also use an not-to-be-named templating system that allow block-based extension. Even though I am primarily a back-end developer, I have run into the exact problem you mentioned numerous times when working on front-end features. Our code is littered with extension blocks that exist only to be used by one specific sub-class and don't make sense to anyone reading the code. There's only one clean solution I've been able to come up with: don't use inheritance.

If your site is small, you honestly don't need any form of reuse or abstraction. Just write the HTML "in the raw". It will ultimately save you more time than wrestling with a complex inheritance hierarchy.

If your site is large, then reusable components are an alternative solution that I prefer. You want to be able to separate a webpage into blocks that may be mixed and matched. One template does not inherit from another template; the pages are all made up of a set of blocks that may or may not be shared between pages. This is what closure templates do as far as I can remember (it's been a while since I've worked with them, but they worked significantly better than the current system I'm working with).

Keep learning

One more thing before I end: read all you can. Don't take my answer or anybody else's answer to this question as scripture. Learn and keep learning. Discover new programming languages, read what others have written, study textbooks on language design. There is always more to know, and the design of languages is constantly evolving.

  • Thanks for taking the time to write this, I suppose I am being too much of an optimist/perfectionist? – Dan Jul 26 '16 at 22:28
  • Also, I am interested in what you wrote about hierarchy basically being a compound of inheritance and subtyping. In most cases, such as when actually programming as you'd say, when I think of the hierarchical tree structure I don't envision child nodes as being subtypes of their parent but rather members within its scope. An example being a button on a control panel. In this case implementing almost random looking functions is often necessary I suppose, correct? – Dan Jul 26 '16 at 22:40
  • 1
    There's no such thing as being too much of an optimist. Always strive to improve your code. Just make sure you're walking down the right path :) I suppose I misunderstood what you precisely meant by hierarchy, but I often see those two concepts intermingled, so I wanted to clear that up. You seem to be talking about composition. That is an extremely useful concept. A button is logically a member of a control panel, absolutely. To provide more feedback I would need to see how you intended to code that up. – gardenhead Jul 26 '16 at 23:20
  • Ok, can I give another example of my problem defining reusable components, but in the context of composition? I feel you have adequately answered my templating problem as it is essentially inheritance. – Dan Jul 26 '16 at 23:57
  • Sure - open another question. You can link to it from here if you like. – gardenhead Jul 27 '16 at 0:08
0

It's impossible to design component to support all unforeseen situations. Adding the button is exactly that. It could be a search box and a button next time, so you never know.

The best approach is to use the simplest approach without complicating things, just add the customizable title (assuming that's what you want right now).

But if a button ever needed, you could change (I'm not sure how JSF works but... hope something like this is possible)

<body>
    <div class="title">
        <insert component="ButtonComponent" default="TitleComponent"></insert>
    </div>
</body>

So you can introduce a component as the title, where it can be changed from page to page. But if it's not needed right now, there is no need to add it and complicate the code because it may never needed.

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.