[英]《Python Web開發》作者Harry Percival:TDD就是微小而漸進的改變(圖靈訪談)
Harry J.W. Percival目前就職於PythonAnywhere,他在各種演講、研討會和開發者大會上積極推廣測試驅動開發(TDD)。他在利物浦大學獲得電腦科學碩士學位,在劍橋大學獲得哲學碩士學位。Harry Percival著有《Python Web開發:測試驅動方法》一書,該書手把手教你從頭開始開發一個真正的Web應用,並且展示使用Python完成測試驅動開發(TDD)的優勢。你將學到如何在開發應用的每一個部分之前先編寫和執行測試,然後再編寫最少量的程式碼讓測試通過——也就是應用TDD理念,寫出簡潔可用、賞心悅目的程式碼。
iTuring: Many agile coaches claim that training newbies to do TDD can be torturous and time-consuming, while there are no garanteed results. What approaches have you adoped in your book to avoid such situation?
That's a tough question! It is impossible to guarantee results when teaching a methodology like TDD, but I think the fact that there are so many TDD books and tutorials out there is proof that, once people have understood it, it changes the way they program, and they feel a lot happier about it, so they want to share it.
There are two ways I think my book is a little different from most. The first is its "conversational" style. Instead of trying to write an academic, lecture-style book, I wrote the book, imagining the reader sitting next to me, working together on a project. That's how I learned TDD myself, by pair-programming with experts. So, rather than trying to deliver a series of lessons or rules, we take a real, practical example, and I demonstrate how to use TDD to address the problem, and I also talk about what's going on in my head, why I make the decisions I make, why use this kind of test or that kind of test.
That's the second aspect that's different, which is that I use a very practical example -- a real project, building a real website, with real functionality. It's simple, but it feels realistic, unlike many tutorials that, for example, ask you to build a "roman numeral translator", or some other abstract example, which seems obvious when you read it but then is hard to apply in the real world.
iTuring: According to you, what are the most effective ways of learning TDD? Is the learning curve of TDD steep?
One way to put it is that TDD is easy in theory, harder in practice. It's easy to get the basic idea TDD with a simple example, like you might find in any online tutorial. But applying that to real-world projects can be tough. It really takes time to get a feeling for what is a good test and what is a bad test, what is useful and what is not productive. Unfortunately the only way to gain that knowledge is with time and experience, but I try to get people started along that road. In the book I tried very hard to keep the learning curve as gentle as possible -- I only introduce one concept as a time, and I tried to keep the early chapters nice and short, with each one introducing just once concept even if it means we learn a simplistic, unrealistic technique at first, just to understand the basic idea, and later on we learn the "real" way of doing it, which is slightly more complex. I think that's a better way to learn than just trying to jump to the perfect solution all in one go. But by the end of the book, the reader will be following on with exactly the kind of TDD techniques that my colleagues and I use every day.
Why do you choose Python as the programming language to approach TDD? Does it have some unique advantages that other languages don't possess? Python tends to be adopted as a teaching language because it's so simple -- it "stays out of the way", by which I mean that Python code is very easy to read, and it doesn't have a lot of boilerplate getting in the way; no "public static void main bla bla" keywords like you might have in java for example. Those kinds of things might be useful for big enterprise applications (although that's debatable!), but they just get in the way when you're trying to teach a programming methodology. So Python is simple, which is great for teaching, but it is also very flexible, which makes lots of TDD techniques easy as well (things like mocking and patching, which I talk about later in the book).
iTuring: For web development, what are the differences between Python Web and ASP.NETWeb? What are their pros and cons?
I'm afraid I don't know anything about ASP.NET, so I'm not really qualified to answer this question. I know that a lot of businesses use ASP.NETbecause it's part of a Microsoft stack that's very familiar, but I also know that a lot of silicon valley startups have used Python to great success (Youtube, Instagram, Reddit, and many more...)
What do you think about Flask? How do you choose between Django and Flask? Flask is simpler but Django has more built-in functionality (or "batteries included", we sometimes say). I've used Flask for small "microservice" applications, but for a larger application Django's features like authentication, the admin UI, and the wide variety of third party plugins and apps make it an appealing choice. But, like any "one size fits all" solution, it can be great, but occasionally the built-in django functionality isn't always exactly what you want. There are trade-offs, but in the end, it's not that important of a decision. You can succeed with either!
iTuring: The more complex a project is, the more tests it requires, sometimes tests take even longer time than developing, which is something a startup cannot afford. So do you have any suggestions for people who have to make tradeoff between testing and developing?
I want to turn this on its head a little. First off, I don't think it's the case that a more complex project means proportionally more time is spent on testing. For the sake of argument, let's say writing a piece of code with tests takes twice as long as writing it without tests (although some people will tell you that, once you get good, you can write it faster with tests than without). But, for the sake of argument, let's say it takes twice the time. I think if it takes twice as long to write code in a very small, simple project, it also takes twice as long in a very large, complex project -- that ratio doesn't change.
What does change is the benefits that tests bring. In a simple project, tests aren't actually all that valuable. If you have a very simple project, it's very easy and quick to test it manually. And if you want to make a major change to the code, maybe upgrading a core module, or refactoring some central algorithm, then you can do it, without tests, check everything quickly, and be fairly confident that everything is OK.
But in a large project it's a very different story. Imagine the largest project you've worked on, and now imagine upgrading one of the core components -- a framework that's used absolutely everywhere in the code, and you want to upgrade to a new version, with a new API and new behaviours. Without tests, that becomes an almost impossible task. Recently, at work, we upgraded our core version of django, and, thanks to tests, it only took us a couple of weeks. But by the end, we could be sure that everything worked, and when we deploy it to our customers, we can have confidence that they won't see any regressions. But without tests, we couldn't have done it. And I mean that literally, without tests, we would simply not have attempted it, it would have been way too risky. And then we would have been stuck on an old version of django, perhaps one that eventually would get so old it would be unsupported, and have all kinds of security problems...
So actually it's in complex projects, after time, that the real benefits of TDD come in. Without tests, you tend to start to get scared to make big changes to your system. You shy away from refactoring, because it's too risky. Technical debt builds up, making new changes becomes more and more difficult, and the engineers working on the system get more and more unhappy.
I talk about this, and my own experience with my first project, in the introduction to the book.
This is one of the real difficulties with testing as a practice - it's an investment. It costs extra time and effort now, and although it can lead to some immediate improvements in the code, the real benefits come in in the future. So it needs some level of forward thinking from the team and from management. But, although speed is critical to a startup, it will die just as fast later if it finds it has too much technical debt to continue innovating and responding to market demands.
iTuring: In TDD, does one have to write test case for each class and method? How to be thorough without spending too much time?
I talk about this a little in chapter 4 in the book. You have to find your own balance. Sometimes you can justify to yourself that, if a function is so small and trivial, maybe it doesn't need a test. But then the danger is: what happens over time? Maybe the simple function grows a tiny bit bigger, it has one more if statement. But it doesn't have tests, and adding new tests is extra effort, so maybe it's ok to just add new code without tests. And then the function grows a for loop, and little by little, it gets more and more complex, and more and more in need of tests, but because of the psychological barrier at each stage, it might never get them. So perhaps it's safer to just have the tests from the very beginning, because adding one new tests when there is already a test there is so much easier. And, after all, if it's such a simple function, then surely it will be very simple to write the first test?
We know that TDD is very effective in projects of small scale, but is TDD able to handle middle-scale or even large-scale projects? Are there anything to look out when you use TDD in large proejcts? As I say, I think some of the real benefits of TDD actually only come in once a project reaches a certain size and a certain age. But, yes, there are things to look out for. One problem is the speed of your test suite. It's easy to take this too far, and some people get obsessed with test speed, but it is important to keep an eye out for it. If you have tests split out into low-level "unit" tests and higher level "functional" tests, then you want to start worrying when your unit tests start to take more than a few minutes to run, or when your functional tests take several hours. Tests are all about trying to get feedback as quickly as possible, within reason. Sometimes you can get into a situation where the speed of your tests stops increasing proportionally to the size of your application, and instead starts increasing geometrically, as complexity increases. But there are ways of dealing with this. I talk about these tradeoffs in the later chapters of the book, particularly in the last chapter (Chapter 22).
iTuring: Legacy code is not always test-friendly, do you have any suggestion about doing TDD on legacy code?
I cannot claim to be an expert in this area, but there is an excellent book on the subject by Michael Feathers called "Working Effectively With Legacy Code". The general advice is: do not despair. It may seem like an impossible task to add tests to a massive existing codebase, but it can be done, gradually and incrementally, over time. Once you've made the decision to start adding tests, then you can, for example, do so whenever a new addition needs to be made to the code, or whenever a bug needs to be fixed. Over time, test coverage will improve, and you start to be able to refactor your application to make it more testable, and the process accelerates.
iTuring: Can front-end TDD be extended to back-end TDD? Are there any models in software engineering worth recommended?
I'm not sure I quite understand this question, but I will try to answer. In the book I talk about using different layers of tests to be able to test both the front-end (the rendering of HTML and the behaviourof javascript, as it appears in a real browser) and the back-end (the controllers and views that connect to the database and process data). By using a layer of "high-level", "real" tests, which I call functional tests, using Selenium, we can test both the front-end and the integration of the whole application. Lower-level "unit" test can be used to test the individual components of front-end javascript and back-end Python code. In the book, in Chapters 18 and 19, I talk about this a little, and models called "Double-Loop TDD" and "Outside-In TDD".
The other thing I should say is that my book isn't just about TDD. It's really about a whole way of doing software engineering in a structured, rigorous, incremental fashion. When I started out coding I was just "hacking", just figuring it out on my own, coding "cowboy-style", and taking shortcuts to make things work. That's fine at first but you soon get into trouble.
What I learned over the next few years, and what I try to communicate in the book, are the tools and techniques to do things in a more structured way. That means TDD, yes, but also means many other things: using a version control tool like git, and making numerous small, incremental commits. It may seem like a separate topic, but in fact it's closely linked to the test-driven way of working, which is all about small, incremental changes. I demonstrate some of the "devops" philosophy, of not just working and testing on your own machine, but also building a staging environment, and using your tests alongside automated deployment scripts to make sure that our code works in production, on a real server, on the internet, as well as on a local machine. I talk about integration with third party systems, and using a continuous integration server to run builds overnight, I talk a little bit about how TDD fits in with agile development methodologies like Extreme Programming (XP)... I really tried to convey everything I learned about the difference between "hacking around" and "real software development" into a book.
更多精彩,加入圖靈訪談微信!
相關文章
- 《Python Web開發》作者Harry Percival:TDD就是微小而漸進的改變(圖靈訪談)PythonWeb圖靈
- 《Python Web開發:測試驅動方法》作者Harry Percival訪談問題有獎徵集(圖靈訪談)PythonWeb圖靈
- 《JavaScript Web應用開發》作者Nicolas:恰巧,愛好變職業(圖靈訪談)JavaScriptWeb圖靈
- 《JavaScript Web應用開發》作者Nicolas Bevacqua訪談問題徵集(圖靈訪談)JavaScriptWeb圖靈
- 《Flask Web開發》作者Miguel Grinberg訪談問題有獎徵集(圖靈訪談)FlaskWeb圖靈
- [英]《釋出!》作者Michael Nygard:質疑軟體開發最基本的假設(圖靈訪談)圖靈
- [英]專訪《寫給大家看的設計書》作者Robin Williams(圖靈訪談)圖靈
- [英]Joe Armstrong:關於Erlang,有很多東西我想改變(圖靈訪談)圖靈
- 《R包開發》作者Hadley Wickham訪談問題有獎徵集(圖靈訪談)圖靈
- [英]《奇思妙想》作者Dennis Shasha:小品電腦科學(圖靈訪談)圖靈
- 《JavaScript快速全棧開發》作者Azat Mardanov訪談問題有獎徵集(圖靈訪談)JavaScript全棧圖靈
- [英]Dave Wooldridge:蘋果應用開發與營銷(圖靈訪談)蘋果圖靈
- 《演算法的樂趣》作者王曉華:“玩”過就是收穫(圖靈訪談)演算法圖靈
- [英]“龍書”作者Jeffery Ullman:相信你自己,自由地思考(圖靈訪談)圖靈
- [英] 《七週七併發模型》作者Paul Butcher:用併發計算實現最大效率(圖靈訪談)模型圖靈
- 《圖靈的祕密》作者Charles Petzold:我眼中的圖靈機和Windows(圖靈訪談)圖靈Windows
- ThinkJS作者李成銀:擇善而從之,篤行致遠(圖靈訪談)JS圖靈
- 《機器學習》作者Peter Flach訪談問題有獎徵集(圖靈訪談)機器學習圖靈
- 《R包開發》作者Hadley Wickham:資料結構“神童”(圖靈訪談)資料結構圖靈
- [英]《禽獸心理學》作者Anna Salter:防止兒童性侵害,從你我做起(圖靈訪談)圖靈
- [英]《JavaScript快速全棧開發》作者Azat Mardanov:現在是擁抱Node技術棧的最佳時機(圖靈訪談)JavaScript全棧圖靈
- 《Android系統服務開發》作者金大佑訪談問題有獎徵集(圖靈訪談)Android圖靈
- 《Docker開發實踐》作者曾金龍:迅雷雲的Docker開發實踐(圖靈訪談)Docker圖靈
- 《演算法圖解》作者Adit Bhargava訪談問題徵集(圖靈訪談)演算法圖解圖靈
- [英]《Swift與Cocoa框架開發》作者Paris Buttfield-Addison:你的程式設計生涯可以從Swift開始!(圖靈訪談)Swift框架程式設計圖靈
- 《特斯拉》作者卡爾森教授訪談問題有獎徵集(圖靈訪談)圖靈
- 《釋出!》作者Michael Nygard訪談問題有獎徵集(圖靈訪談)圖靈
- [英]《簡約至上》作者Giles Colborne:讓使用者變成設計的一部分(圖靈訪談)圖靈
- 《七週七併發模型》作者Paul Butcher訪談問題有獎徵集(圖靈訪談)模型圖靈
- 《圖靈的祕密》作者Charles Petzold訪談問題徵集圖靈
- [英]《HTTP權威指南》作者Anshu Aggarwal:用計算機來節能(圖靈訪談)HTTP計算機圖靈
- 鍾冠賢:iOS開發之路(圖靈訪談)iOS圖靈
- 《釋出!》作者Michael Nygard:質疑軟體開發最基本的假設(圖靈訪談)圖靈
- 《跟阿銘學Linux》作者李世明:談不上告白,就是幫女友轉型而已(圖靈訪談)Linux圖靈
- 《CSS揭祕》作者Lea Verou訪談問題有獎徵集(圖靈訪談)CSS圖靈
- 《鳳凰專案》作者基恩·金訪談問題有獎徵集(圖靈訪談)圖靈
- [英]《Linux/Unix設計思想》作者Mike Gancerz:Linux/Unix哲學的印證(圖靈訪談)Linux圖靈
- [英]《資料科學實戰》作者Cathy O'Neil:大資料並不神奇(圖靈訪談)資料科學大資料圖靈