TLDR; I don’t start coding with patterns. I code for value, then generalise as needed. I refactort to abstractions, some of which use patterns.
A Twitter Conversation
I received comments, via twitter, on a webinar from Roy de Kleijn (@TheWebTester)
The basic twitter conversation read:
- Roy: “It’s a pity that there are no design patterns in the source. Any reason for this?”
- Alan: “Yes. I don’t start with patterns. I code for value, then generalise as needed. I did use domain objects, a pattern of sorts.”
- Roy: “fair enough, what about the value of maintenance? I usually start with patterns because people work in bigger environments”
- Alan: “In the webinars I will grow the code, explaining my decisions at each point. Patterns will influence me as the code grows.”
- Roy: “valid reason 🙂 it was just something I noticed…”
- Alan: “:) good, keep commenting, we have to choose between coding styles, and justify our decisions, so all questions help”
- Roy: “or choose both and let the scripts evolve.We have the challenge that also (a lot) non-technical people joining the trainings. how you deal with that ?”
- Alan: “During training I explain my decisions. I point out alternatives, and “but right now, I choose this because… x, y and z”
- Roy: “What about if people don’t have program skills/experience at all ? are they in the wrong place ?”
- Alan “I believe people who want to learn, can do so quickly, via osmosis, of stuff they don’t yet grasp, when they see it done.”
- Roy: “I like the idea of osmosis, will try to do this more during next trainings… Thanks for your advice!”
- Alan: “You’re welcome. Hope it helps.”
And I want to elaborate on the conversation above in this post because I think Roy draws out a bunch of really important points here.
What no patterns?
In the webinars, I code the way I code in the real world. With the difference that I explaining as I go. And I find that hard, I won’t discuss that here, but I don’t feel used to doing that. I want to do that in the webinars because it helps people understand the decisions I make, and I that helps me draw down on experience that the participants in the webinar may not have.
e.g. If I choose to write a class with a public final field rather than add an accessor method then I explain that I could add an accessor method, but at the moment I want to encourage the flow of coding, and I want to write code that maintains the flow. I need something that I can access, which has a value, which won’t change. And an accessor method can give me flexibility in how I calculate or generate that value. But at that precise moment I don’t really need that flexibility. I might need it in five minutes time, but I don’t need it now. So I also try to explain that I can change this at any point in time.
The knowledge that it can change quickly allows me to make decisions quickly. Knowing that I will revisit the decisions that I have made.
I try to adopt a flexible approach when I code. And sometimes I experiment with approaches to see how far I can simplify them before I experience pain. I don’t necessarily have the aim to set out an exemplar coding style in the webinar code, but I do want to make people aware of options.
I build what I need, when I need it, and evolve
I also don’t start with patterns. I have experience of patterns, but I don’t start there. I know when I write tests that I’ll probably need Page Objects, but I don’t start there. I let the test itself justify the need for scaffolding around it.
- If I only ever right one automated test on a project. I don’t need a Page Object.
- If I write two test methods, for the same page then I don’t yet need a Page Object. I need some local methods in the test class to avoid repeated code.
- If I write three test methods, and they no longer all reside in the same test class. Then I might think about a page object because the repeated code I need has different classes accessing it.
Now I could have started with the Page Object, because I thought I’d write a lot of tests. But I don’t.
I write simple code. Refactor chunks out into higher levels of abstraction, as the use of that abstraction becomes necessary. And when I refactor into higher levels of abstraction, the patterns and aproaches that I know, help me decide how to refactor.
I think that this leads to maintainable code. And it also leads to code which I own and have an attitude of non-permanence towards. i.e. I don’t start with patterns, so I don’t think my code has a good design. I refactor based on usage, so as I see better ways of using it, I will change it, constantly.
The code we write should add value
I think this also forces the code to add value.
A test method, with no abstraction, written quickly, can add value faster than a framework and set of Page Objects, with no tests that use them.
What about maintenance?
I don’t believe Roy meant “create a framework” when he asked about maintenance. I think he meant - “Alan, you don’t just ignore maintenance and longer term concerns do you?” and I don’t, I evolve to them.
I take this approach when I code. And I take this approach in the Webinar. Explaining my decisions and pointing out alternatives as I go, and making decisions, that I can justify and explain while understanding the pros and cons of each decision. Because each line of code offers us a decision point and we have to understand why we make the decision we make to code intelligently.
What about experience?
Roy also brings up the point about, what “if people don’t have program skills/experience at all”. Can they learn like this?
I believe they can. I don’t pretend to have expertise in learning theory. But I know the approaches I take to learning.
The Webinars use an osmosis learning style. By watching someone do something you see that someone can do the task. You have evidence of the possibility. So you know when you come to do it, that it can work. Useful knowledge for a beginner because beginners make mistakes, and if you don’t know the mistake originates from you, instead you think that you have encountered an impossible action, you stop.
When I studied at University, I read as many books on each topic as I could. Regardless of whether I had the necessary knowledge to understand that particular section in that particular book. Because I knew that if I read a lot of them, and read them quickly, then my brain would assimilate the information and I would advance more quickly through the material that the linear tutorials and lectures led me through.
I recommend reading around your study topic as much as possible. Quickly. Jump backwards and forward through the material. Jump to advanced, so when you come back to your current ‘ready for it’ level, then it seems simple in comparison, and you have foresight into where it will go.
I use this experience as a basis for the Webinars. The linear progression in the webinar comes from the creation of the tests and the automation. But the knowledge around that comes out of order, I base it on experience, I’ll name drop Page Objects without explaining them, etc. because people will take what they need at that time and develop an awareness for other concepts that we will refer to again because they form part of the automation context and domain.
I have designed the webinars to supplement self study and other linear styles of learning e.g. the online courses I put together have a linear path through the API, or a linear path through the initial setup steps.
Thanks to Roy for the twitter questioning. And hopefully you can see why 140 chars don’t let me fully express myself.
Recommended Reading:
And in a spirit of giving you more information to explore, I recommend:
- Kent Beck’s “Implementation Patterns” book, which encouraged me to keep things simple
- Steve Freeman, and Nat Pryce “Growing Object-Oriented Software”, which helped me see additional nuances around growing code
By the way. I’m not suggesting that either of these books or people have recommended the approaches I’m describing. But I think the books do a similar job of explaining decisions as part of the coding process.
Add Structure Later
I sent this blog post to Roy to review to make sure he was happy with the name check. And he gave me his approval. He also said.
“One note: I think if you work with multiple people on the same automation project, you will need some structure or patterns.
Don’t you think ?
For a small web application this approach is fine, but if you do automation for a bank or insurance company… And you are part of a team of automated testers..”
And I do agree that Yes, when working with multiple people you need to introduce structure at some point.
This is when the code moves from a Tactical “just get it done” state to a Strategic “We are going to live with this for a while” state.