vendredi 20 janvier 2017

Is procedural code ever appropriate for rendering a UI View?

Background

At work, I ran into some code that used a series of procedural methods to build an HTML View. It felt really wrong to me, and while working on it, I managed to introduce unintended layout changes.

See the pseudo-code below for a more detailed explanation.

Questions

  • The project was an ASP.NET web application targeting the 4.0 framework. With all the tools available to an ASP.NET developer, is there any reason this pattern would be appropriate.

  • Ultimately, given no other time priorities, should this code be refactored ? It definitely smells of code fragility.

Caveats

I'm not 100% sure if this is an appropriate question for SO. It falls in the somewhat subjective topic of programming patterns. As a subjective topic, there is the potential for the SO Answers to devolve into a discussion, which as we all know, is not the purpose of SO. I don't think this question qualifies as code-golf.

What I'm looking for is objective evidence that this particular pattern is either a bad idea for some reason such as it leads to unmaintainable code. Or evidence that this pattern is appropriate for certain situations, bonus points for citing a specific example.

Had I written this code, I would have probably used some sort of well-known templating engine. I'd handle the logic decisions (highlight rows for people who have birthdays) in non-view code. I suppose I'm a proponent of logic-less template engines.

I apologize for the long code, I tried to keep it terse without sacrificing context. Hopefully, this will be a fun question to answer for some battle-scarred SO veteran.

The Code

About the pseudo-code

The code in this question does not represent any actual programming language. It is mostly based on JavaScript with HTML terms thrown in there. It should be easy enough to interpret without significant mental gymnastics.

page load event handler

protected void Page_Load(object sender, EventArgs e) {

    var data = DataLayer.getData();
    var engine = new DataViewRenderEngine(data);
    var divElement = engine.Render();

    document.body.add(divElement);

}

Definition of DataViewRenderEngine

class DataViewRenderEngine {

    private _dataSource = null;

    public DataViewRenderEngine(dataSource) {
        this._dataSource = dataSource;
    }

    public Element Render() {
        return RenderView(this._dataSource);
    }

    private Element RenderView(data) {

        var containerDiv = RenderContainerDiv(data);            

        var pageHeader = PenderPageHeader(data.Title);
        containerDiv.add(pageHeader)    

        var personTable = renderPersonTable(data.PeopleArray)
        containerDiv.add(personTable);

        return containerDiv;        

    }

    private Element RenderContainerDiv() {
        return new Element({
            tag: 'div',
            class: 'container'
        });
    }

    private Element RenderPageHeader(title) {       
        return new Element({
            tag: 'h1',
            innerHTML: title        
        });     
    }

    private Element RenderPersonTable(peopleArray) {

        var table = new Element('table');

        for(var person in peopleArray) {
            var row = RenderPersonTableRow(person);
            table.add(row); 
        }

        return table;
    }

    private Element RenderTableRow(person) {
        var row = new Element('tr');

        row.add(new Element({
            tag: 'td',
            innerHTML: person.firstName     
        });

        row.add(new Element({
            tag: 'td',
            innerHTML: person.lastName      
        });

        var today = Date.Today();
        if(person.birthday.Month == today.Month &&
           person.birthday.Day   == today.Day) {
            row.BackgroundColor = 'green';
        }

        return row; 
    }

}

Aucun commentaire:

Enregistrer un commentaire