Agile FAQs
  About   Slides   Home  

 
Managed Chaos
Naresh Jain’s Random Thoughts on Software Development and Adventure Sports
     
`
 
Discovering...
Industrial Logic

Microblog Feed
    Previous Feeds...
    Recent Thoughts

    Demo during XP Planning Game
    Demo during XP Planning Game
    Recent Comments
    Categories
    Archives
    March 2010
    M T W T F S S
    « Feb    
    1234567
    891011121314
    15161718192021
    22232425262728
    293031  
    RSS Feed
    Add to Technorati Favorites

    Embracing Context Objects with Fluent Interfaces for my Tests

    Thursday, September 24th, 2009

    Of late I’ve been toying around with a new way of using Fluent Interfaces with a Context Object for my Tests. Esp. when I’m using Mockito.

    In this post (Fluent Interfaces improve readability of my Tests), I’ve taken an example and demonstrated how I’ve evolved my tests to be more expressive. In my quest for getting my tests to communicate precisely to-the-point by hiding everything else which is noise, I’ve stared exploring another way of using Fluent Interfaces.

    Following is an example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    @Test
    public void redirectSubDomainsPermanently() {
        lets.assume("google.com").getsRedirectedTo("google.in").withSubDomain();
        response = domainForwardingServer.process(requestFor("blog.google.com"));
        lets.assertThat(response).contains(StatusCode.PermanentRedirect)
                                 .location("google.in/blog").protocol("HTTP/1.1")
                                 .connectionStatus("close").contentType("text/html")
                                 .serverName("Directi Server 2.0");
    }

    lets and on are both Context objects which provide fluent, domain specific api to make the test very easy to read (communicative and expressive). It also helps me hide all my mocking/stubbing related code.

    If you compare this with the original code, you can get a sense of what I’m talking about:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    @Test
    public void redirectSubDomainsPermanently()  {
        when(request.hostName()).thenReturn("blog.google.com");
        when(request.protocol()).thenReturn("HTTP/1.1");
        when(request.path()).thenReturn("/");
        domain.setDomain("blog.google.com");
        domain.subDomainForwarding(true);
        domain.setForward("google.in");
        response = domainForwardingServer.processMessage(request);
        assertStatus(StatusCode.PermanentRedirect);
        assertLocation("google.in/blog");
        assertProtocol("HTTP/1.1");
        assertConnectionStatusIs("close");
        assertContentType("text/html");
        assertServerName("Directi Server 2.0");
    }

    Another example showing the Context object and Fluent Interface style is

    1
    2
    3
    4
    5
    6
    
    @Test
    public void avoidRestrictedWordsInIds() {
        lets.assume("naresh").isARestrictedUserName();
        List<String> suggestions = suggester.optionsFor(naresh_from_mumbai);
        lets.assertThat(suggestions).are("nares@jain.com", "nares@india.com", "nares@indian.com", "nares@mumbai.com");
    }

    As I said, I’m still toying around with this idea. If this works well, may be it will be part of some mocking framework soon.

    • Share/Bookmark

    Are comments Evil?

    Wednesday, August 19th, 2009

    Today @Directi we had a few freshers from college come down for an interview. As part of the interview process, I was making a presentation to them about code smells. During this I was thrashing the whole “comments in code” universal best practice.

    During this Ramki was sitting and he silently wrote me an email asking “Are comments evil?” His email follows:

    Naresh,

    Can you please opine if comments are bad in the following scenario:
    (For this project dojo is a dependency and is not owned/maintained by the guys using it to write this code)

    this.show = function(){
        this.view.show();
        //this is a hack, dojo seem to have an issue in rendering
        //dynamically/programmatically generated widgets.
        //We *should* call resize() to ensure that the widget is appropriately rendered
        this.view.resize();
    }

    —- Vs. ——-

    this.show = function(){
        this.view.show();
        this.view.resize();
    }

    In the later case where comments are removed or say never written, though the user understands that you are resizing he would still be wondering why am I calling resize() when I am just showing..?

    This is a great question Ramki.

    I always say that comments are evil and we should not write comments. Also the first thing I do when I see some code is delete all the comments in it. This is an over generalized comment.

    What I really mean:

    Writing comments that explain “how” or “what” is evil. Comments (esp. about what and how) is a clear failure to express the intent in code. Comment is a deodorant to hide that failure (smell). However sometimes “the why” is not apparent and if you don’t find a suitable way to communicate that through code, comment is the fall back option. Note that comments are a fall back option rather than a default option.

    At times, one has to think hard to write code that expresses intent rather than write some sloppy code with poor abstractions and get away by writing comments.

    In my Self Documenting Code blog I show a similar example and explain the thinking process.

    In case of your code I could write it as follows:

    this.show = function(){
        this.view.show();
        reRenderDynamicallyGeneratedWidgets_dojoHack(this.view);
    }
     
    function reRenderDynamicallyGeneratedWidgets_dojoHack(view){
        view.resize();
    }

    This is really pushing it, but I hope you understand where I’m heading with this.

    • Share/Bookmark

    Source Code is the Design

    Sunday, February 1st, 2009

    Following a DesignFest @ Directi, there has been a lot of discussion on “what is Design?”, “should one design before they code?” and so on.

    In this blog I’ll be mostly focusing on object design. There are other designs related to Usability which is not the focus. However I believe it is very important to incorporate various other design elements into your object design to achieve Conceptual Integrity.

    I strongly recommend you read the following before you continue reading this blog:

    So where does this whole notion of design followed by coding come from?

    On the C2 Wiki there is a really nice response to this question:

    I propose that the real issue is that design is not really a beneficial activity in software development, and to say “The Source Code Is The Design” is trying to use semantics to gloss over the issue.

    I feel this is an important distinction if the goal is to remove the “design” stage from the software development process. Rather than being afraid of being accused of “not doing design”, we need to turn the debate around to be “Why should we do design?”

    For some tasks (in other industries like Manufacturing), it may be much more cost effective to create a design and evaluate the design before building the actual product. For software, this is not the case. For years, software has struggled to come up with something to use for “design.” We had flow charts, PDL, Data Flow Diagrams, prose descriptions, and now UML. With software, however, it takes as much time to create the design as the actual software; the design is more difficult to validate than the actual software; and the simplifying assumptions made in the design are often the critical issues to evaluate in the software. For these reasons, it simply is not cost effective to design, iteratively correct the design, then write the software (and then iteratively correct the software). It is better to start with the software and iteratively correct it.

    I believe it is time to explicitly state the long held secret of software, we do not need to do design; design is ineffective and costly.

    I would saying mandating that you need to design first does not seem right. It’s also important to understand that:

    UML diagrams and other associated paperwork (if any) are documentation about the design. A documentation can have different views as appropriate to shed some light (if any) on various aspects of the object described. However, the source code has a privileged status: it is not just “documentation about”, it is the object itself.

    If documentation is important why not use source code as that document? Of course this means programmers will now have to write self-documenting code which embraces Simple Design.

    • Share/Bookmark

    Self Documenting Code Example

    Saturday, November 8th, 2008

    Yesterday a colleague @ Directi was writing some code and was very unhappy about the code. He was not sure how to write the following method without having to add a comment to explain the rationale behind the code’s logic.

    1
    2
    3
    4
    5
    6
    
    private HttpSession renewSession (HttpServletRequest request, HttpServletResponse response)
    {
      HttpSession session = webUtils.getSession(request, response);
      session.invalidate();
      return webUtils.getSession(request, response);
    }

    The method name expressed what the code was doing (renewing an existing session) but the “why” it was doing what it was doing was missing. The why is very important for someone to understand. This method was invoked from the following method:

    1
    2
    3
    4
    5
    6
    
    void createAuthenticatedSessionUsingAuthenticatedEntity (HttpServletRequest request, HttpServletResponse response)
    {
      HttpSession session = renewSession(request, response);
      AuthenticationInfoBean authInfoBean = authUtils.getAuthInfoBean (request);
      session.setAttribute(getAuthenticatedUserBeanKey(), authenticatedBeanCreator.create(authInfoBean.getUsername(), authUtils.getValidatedEntity(request)));
    }

    One option was to rename renewSession method to renewUnAuthenticatedSessionToEliminateSesionFixationByInvalidatingSession. But in the context where this method was used, it would be too much noise. Not always I’m interested in how and why the session is renewed.

    Another option is to write a JavaDoc for the renewSession method. Personally I hate JavaDocs and I was interested to find a way to eliminate that. So I asked the developer to first write the JavaDoc to express what he wanted to express. He wrote:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    /**
    * This method retrieves the unauthenticated session, then invalidates the session to eliminate session fixation issue and creates a new authenticated session.
    * @param request HttpServletRequest
    * @param response HttpServletResponse
    * @return HttpSession Authenticated Session.
    */
    private HttpSession renewSession (HttpServletRequest request, HttpServletResponse response)
    {
      HttpSession session = webUtils.getSession(request, response);
      session.invalidate();
      return webUtils.getSession(request, response);
    }

    Now looking at the comment it was easy for me to figure out how to write the code such that the comment is not required. This is what we ended up creating.

    1
    2
    3
    4
    5
    6
    
    private HttpSession renewSession(HttpServletRequest request, HttpServletResponse response)
    {
      HttpSession session = retrieveUnAuthenticatedSession (request, response);
      eliminateSesionFixationByInvalidatingSession (session);
      return newlyCreatedAuthenticatedSession (request, response);
    }

    Again its arguable if writing code this way is much better that writing a small JavaDoc comment. As a rule of thumb, I always prefer self-documenting code over code which needs comments to support it. The real problem comes from the fact the comments soon fall out of place with the code. And why spend all the extra time maintaining code, its comments and also making sure they are in sync.

    • Share/Bookmark
        Licensed under
    Creative Commons License
    Design by vikivix