Agile, Architecture, Design Pattern, Devops, Methodology, Microservices, OO Design Principles, TDD

InfoQ’s 2019, and Software Predictions for 2020

See full post at: https://www.infoq.com/articles/infoq-2019-retrospective/

Key Takeaways

  • Last month, Google claimed to have achieved quantum supremacy—the name given to the step of proving quantum computers can deliver something that a classical computer can’t. That claim is disputed, and it may yet turn out that we need a better demonstration, but it still feels like a significant milestone.
  • A surprise this year was the decline of interest in Virtual Reality, at least in the context of Smart-phone-based VR. Despite this we still think that something in the AR/VR space, or some other form of alternative computer/human interaction, is likely to come on the market in the next few years and gain significant traction.
  • We expect to see the interest in Web Assembly continue and hope that the tooling for it will start to mature.
  • In our DevOps and Cloud trend report, we noted that Kubernetes has effectively cornered the market for container orchestration, and is arguably becoming the cloud-agnostic compute abstraction. The next “hot topics” in this space appear to be “service meshes” and developer experience/workflow tooling.
  • We’re looking forward to seeing what the open source community and vendors are working on in the understandability, observability, and debuggability space in the context of architectural patterns such microservices and functions(as-a-service).

Development

Java

JavaScript, Java, and C# remain the most popular languages we cover, but we’re also seeing strong interest in Rust, Swift, and Go, and our podcast with Bryan Cantrill on “Rust and Why He Feels It’s The Biggest Change In Systems Development in His Career” is one of the top-performing podcasts we’ve published this year. We’ve also seen a growing interest in Python this year, probably fuelled by its popularity for machine learning tasks.

After a rather turbulent 2018, Java seems to be settling into its bi-annual release cycle. According to our most-recent reader survey Java is the most used language amongst InfoQ readers, and there continues to be a huge amount of interest in the newer language features and how the language is evolving. We also continue to see strong and growing interest in Kotlin.

It has been interesting to see Microsoft’s growing involvement in Java, joining the OpenJDK, acquiring JClarity, and hiring other well known figures including Monica Beckwith.

In the Java programming language trends report, we noted increased adoption of non-HotSpot JVMs, and we believe OpenJ9 is now within the early-adopter stage. As the time we noted that:

“We believe that the increasing adoption of cloud technologies within all types of organisation is driving the requirements for JREs that embrace associated “cloud-native” principles such as fast start-up times and a low memory footprint. Graal in itself may not be overly interesting, but the ability to compile Java application to native binaries, in combination with the support of polyglot languages, is ensuring that we keep a close watch on this project.”

.NET

The release of .NET Core 3 in September generated a huge buzz on InfoQ and produced some of our most-popular .NET content of the year. WebAssembly has been another area of intense interest, and we saw a corresponding surge in interest for Blazor, a new framework in ASP.NET Core that allows developers to create interactive web applications using C# and HTML. Blazor comes in multiple editions, including Blazor WebAssembly which allows single-page applications to run in the client’s web browser using a WebAssembly-based .NET runtime.

According to our most-recent reader survey, C# is the second-most widely used language among InfoQ readers after Java, and interest in C#8 in particular was also strong.

Web Development

Unsurprisingly, the majority of InfoQ readers write at least some JavaScript – around 70% according to the most recent reader survey – making it the most widely used language among our readers. The dominant JavaScript frameworks for InfoQ readers seem to currently be Vue and React. We also saw interest in using Javascript for machine learning via TensorFlow.js.  Away from JavaScript, we saw strong interest in some of the transpiler options. In addition to Blazor, mentioned above, we saw strong interest in Web Assembly, Typescript, Elm and Svelte.

Architecture

It’s unsurprising that distributed computing, and in particular the microservices architecture style, remains a huge part of our news and feature content. We see strong interest in related topics, with our original Domain Driven Design Quickly book, and our more-recent eMag “Domain-Driven Design in Practice” continuing to perform particularly well, and interest in topics like observability and distributed tracing. We also saw interest in methods of testing distributed systems, including a strong performance from our Chaos Engineering eMag, and a resurgence in reader interest in some for the core architectural topics such as API design, diagrams, patterns, and models.

AI, ML and Data Engineering

Our podcast with Grady Booch on today’s Artificial Intelligence reality and what it means for developers was one of our most popular podcasts of the year, and revealed strong interest in the topic from InfoQ readers.

Key AI stories in 2019 were MIT introducing GEN, a Julia-basd language for artificial intelligence, Google’s ongoing work on ML Kit, and discussions around conversational interfaces, as well as more established topics such as streaming.

It’s slightly orthogonal to the rest of the pieces listed here, but we should also mention “Postgres Handles More Than You Think” by Jason Skowronski which performed amazingly well.

Culture and Methods

If there was an overarching theme to our culture and methods coverage this year it might best be summed up as “agile done wrong” and many of our items focused on issues with agile, and/or going back to the principles outlined in the Agile Manifesto.

We also saw continued in interest in some of the big agile methodologies, notably Scrum, with both “Scrum and XP from the Trenches“, and “Kanban and Scrum – Making the Most of Both” performing well in our books department.

We also saw strong reader interest in remote working with Judy Rees’ eMag on “Mastering Remote Meetings“, and her corresponding podcast, performing well, alongside my own talk on “Working Remotely and Managing Remote Teams” from Aginext this year.

DevOps and Cloud

In our DevOps and Cloud trends report, we noted that Kubernetes has effectively cornered the market for container orchestration, and is arguably becoming the cloud-agnostic compute abstraction. The next “hot topics” in this space appear to be “service meshes” and developer experience/workflow tooling. We continue to see strong interest in all of thee among InfoQ’s readers.

A trend we’re also starting to note is a number of languages which are either infrastructure or cloud-orientated. In our Programming Languages trends report, we noted increased interest and innovation related to infrastructure-aware or cloud-specific languages, DSLs, and SDKs like Ballerina and Pulumi. In this context we should also mention Dark, a new language currently still in private beta, but already attracting a lot of interest. Somewhat related, we should also mention the Ecstasy language, co-created by Tangosol founders Cameron Purdy and Gene Gleyzer. Chris Swan, CTO for the Global Delivery at DXC Technology, spoke to Cameron Purdy about the language and the problems it’s designed to solve.

Software Predictions for 2020

Making predictions in software in notoriously hard to do, but we expect to see enterprise development teams consolidate their cloud-platform choices as Kubernetes adoption continues. Mostly this will be focussed on the “big five” cloud providers – Amazon, Google, IBM (plus Red Hat), Microsoft, and VMware (plus Pivotal). We think that, outside China, Alibaba will struggle to gain traction, as will Oracle, Salesforce, and SAP.

In the platform/operations space we’re expecting that service meshes will become more integrated with the underlying orchestration frameworks (e.g. Kubernetes). We’re also hopeful that the developer workflow for interacting with service meshes becomes more integrated with current workflows, technologies, and pipelines.

Ultimately developers should be able to control deploy, release, and debugging via the same continuous/progressive delivery pipeline. For example, using a “GitOps” style pipeline to deploy a service by configuring k8s YAML (or some higher-level abstraction), controlling the release of the new functionality using techniques like canarying or shadowing via the configuration of some traffic management k8s custom resource definition (CRD) YAML, and enabling additional logging or debug tooling via some additional CRD config.

In regards to architecture, next year will hopefully be the year of “managing complexity”. Architectural patterns such microservices and functions(as-a-service) have enabled developers to better separate concerns, implement variable rates of change via independent isolated deployments, and ultimately work more effectively at scale. However, our ability to comprehend the complex distributed systems we are now building — along with the availability of related tooling — has not kept pace with these developments. We’re looking forward to seeing what the open source community and vendors are working on in the understandability, observability, and debuggability space.

We expect to see more developers experimenting with “low code” platforms. This is partly fueled by a renewed push from Microsoft for its PowerApps, Flow, Power BI, and Power Platform products.

In the .NET ecosystem, we believe that Blazor will keep gaining momentum among web developers. .NET 5 should also bring significant changes to the ecosystem with the promised interoperability with Java, Objective-C, and Swift. Although it is early to say, Microsoft’s recent efforts on IoT and AI (with ML.NET) should also help to raise the interest in .NET development.  Related we expect to see the interest in Web Assembly continue and hope that the tooling hear will start to mature.

Despite the negative news around VR this year, we still think that something in the AR/VR space, or some other form of alternative computer/human interaction, is likely to come on the market in the next few years and gain significant traction, though it does seem that the form factor for this hasn’t really arrived.

Agile, TDD

Patterns of Effective Teams

Again, Dan North, again great talk!

The talk was going around the following map:

Patterns

Dreyfus Squared

  • Different levels of people, do the pairing!, share the love and knowledge within the team

Shallow Silos

  • Rotate team/pairs

Seize of Day

  • Energize standups, discuss the status, not just report!, we don’t care about the brief status: I did XYZ, I will do ABC, I have no issues. Do the real scrum as it was inspired from american footbal to decide what the team will do now, today and how it’s going to solve the current problems.

Near and far

  • Cross-funcational teams vs. single specialized teams
    • solution in the middle, keep having very specialized teams but ask them to teach cross-functional teams

Warm welcome

  • already covered in his previous talk

Code Critique aka code reviews

  • Learning from others
  • Socializing

Team Hack Days

  • “TODO” days
  • “SMELLS” days – fix the smells in the code, I know, you don’t have smell in the code, just in case 😉
  • “RESEARCH” days
  • go and play with non-project tasks
  • => getting people together, great ideas can evolve

Walk a mile:

  • What’s the benefit of person (dev, manager)
    • Walk in his/her shoes
    • Take him off and let’s see

TDD

  • Can slow down in case I don’t know where you are heading to, i.e. prototyping, proposing different solutions,
  • Find a balance where it’s needed, some simple code could be verified by explanatory tester and it’s wasting of dev time

From https://blogs.msdn.microsoft.com/fkaduk/2013/06/12/ndc-oslo-2013-day-1/

Chưa phân loại, TDD

TDD, where did it all go wrong

General

There are different kinds/levels of testing:

  • Unit testing:
    • testing class/method:
      • Helps us to get good design, but coupled to the implementation details
      • Implementation details is going to be changed so that we need to change also our class/method tests => which is expensive and we are lazy to do it => we skip it and the tests are dead
    • Testing behaviour:
      • HERE should be the focus
      • When implementation details have changed but behaviour stayed same, these tests are untouched and we should be free to refactor them
  • Integration testing
    • Testing componentization
      • Should be small amount of them
  • UX testing

ATDD

  • hard to maintain
  • Written by business analysts, customers, maintained by devs => nightmare,
  • Results in RED state
  • What’s the value  having them? They are veeery expensive

 Where did all go wrong?

  • Writing UT against classes, methods

Read the book written by Kent Beck: Test driven development by example to understand more, should be like a bible for devs who takes testing seriously

Zen of testing

  • Don’t write tests against UX
  • UX is going to be changed so your tests have to be changed
  • Let UX devs write them

Write tests against surface of module , avoid testing against implementation, don’t couple to implementation, couple to the behavior

Testing should be done using simple steps:

  • Get solution to the problem fast
  • Don’t solve the problem and engineer together, split them! Then unit testing becomes a part of problem solving task
  • Result:
    • Write hacky code just to make test working but DON’T STOP THERE!!! please
  • Engineeirng comes later => in form of refactoring!!!!, please, keep it in mind!

Result

DON’T COUPLE TESTS TO IMPLEMENTATION DETAILS!!!!!!

=> you write less tests

Common issue

Ice cream problem:

  • Manual testing is too expensive
  • Automated GUI tests – we need to rewrite them as soon as UI changes, they are never done, stays RED
  • Most useful and the cheapest are UT

Unit Tests – focused on business logic, behavior,

Integration testing: cooperation between components

UI – testing:

  • UI widgets testing
  • Keep them manual

It should be like this:

Hexagonal architecture

  • In the center there is a Domain Model
  • Around it there are so called ports – application program interfaces – which makes surface of the system
  • Around them we have port adapters (MVC adapter, DB adapter, Notification adapter …) <= this we need to fake in order to
  • We test around ports! – public API

TDD/BDD

  • Don’t test the things you don’t own
  • UT  coupled to the implementation helps us with a design but don’t be afraid to delete them. Tests on higher level should be kept long-term only.

 ATDD

  • Can help to clean-up the communication developer vs. business
  • Very expensive, business people don’t want to do it

Summary

  • BDD is unit testing on the higher level ..
  • DON’T mock internals
  • MOCK port to adapter

From https://blogs.msdn.microsoft.com/fkaduk/2013/06/14/ndc-oslo-2013-day-3/

Book, Design Pattern, TDD

Book Review: xUnit Test Patterns: Refactoring Test Code: Gerard Meszaros

Khi đối diện với những điều không (chưa) biết, kẻ bi quan sẽ tỏ ra lo sợ và trốn chạy, người lạc quan thì không như vậy, họ luôn biết cách đối mặt với nó.

Vào những năm cuối thập niên 90, khi phong trào eXtreme Programming mới bắt đầu được khai nén, đã có những nhóm, những nhà tiên phong đi đầu trong việc áp dụng các kỹ thuật của nó như pair programming, collective ownership và test driven development. Tuy nhiên, họ đã gặp phải rất nhiều vấn đề trong đó, ví dụ như là làm thế nào để apply TDD, viết và quản lý test code cho real-world project. Khi production code lẫn test code bắt đầu phình ra cũng là lúc họ nhận ra rằng ngày càng tốn nhiều effort chỉ để làm những công việc lặp đi lặp lại. Đã có lúc, đến 90% effort bỏ ra chỉ cho việc maintenance những unit test cases đã có chỉ để đáp ứng một thay đổi cực kỳ minor. Một con số thật sự làm nản lòng và gây hoang mang dù là những người lạc quan nhất. Và họ biết, họ cần phải làm gì đó để thay đổi điều đó.

3394674118_28fd307467

TDD, kẻ thì khen, người thì chê. Kẻ khen thì trầm trồ về sự ưu việt của nó, kẻ chê thì nói TDD thực sự chỉ là 1 thứ rối rắm, tốn nhiều công lắm của mà không thực sự giải quyết được bài toán mà họ gặp phải. Nhưng có mấy kẻ hiểu được làm TDD như thế nào cho effective. Khi đối diện với một dự án phức tạp, vấn đề gây đau đầu nhất trong mỗi lần thay đổi source code chính là degradation, làm sao để analyze và thực hiện regression test để bảo đảm code change là “vô hại” đến những phần khác. Những lúc như vậy, ai cũng mong có một bộ automated test để phòng thân, nhưng cái giá của nó không phải là free, hoặc có thể là vô giá.

Prorgramming is hard, hay nói cách khác, tạo ra những đoạn code trong sáng, dễ maintain và extend là không dễ. Trừ khi ta nắm được các bí quyết để làm chuyện đó. Bằng cách nhận biết đâu là những đoạn code tệ (code smell), hay mở rộng ra là project smell, architecture smell, environment smell, ta sẽ biết cách để sửa chữa chúng. Refactoring những chỗ không tốt thành tốt hơn đòi hỏi những kỹ thuật cao hơn như nắm vững các coding, design principle, patterns. Khi đó, code sẽ trở nên sáng sủa và vững vàng hơn nhiều, programming is now easy and much more exciting, like a joy!! ^^

Testing is extremely hard, vì trường học không (kịp) dạy ta các kỹ năng về kiểm thử. Programmer thích lập trình, sợ bugs, ghét tester… nên đâm ra ghét testing. Đặc biệt không có anh nào code dở mà có thể test (unit, at least) giỏi, mấy người như vậy qua làm tester hết rồi. Còn lại những anh code dở và test cũng dở, và những anh code vốn giỏi mà test dở. (Chỗ này hại não =)) Với những anh code giỏi thì khả năng để improve kỹ thuật testing là tương đối dễ dàng, những anh khác, vui lòng quay lên phần “Programming is hard”.

Để make (Unit) Testing more fun and do-able, việc đầu tiên chính là phải code giỏi cái đã. “Code that hard to test is the bad code”. Vậy làm sao để nhận diện đâu là code tệ? Đa phần đã nghe đến code smell, vậy còn test smell. Sử dụng test smell để nhận diện các vấn đề gây khó khăn cho việc viết test là bước đầu tiên. Test smell có thể bao hàm rất nhiều thứ kể cả code smell. Bên cạnh đó, cũng giống như programming, testing cũng có principle và pattern của nó. Nói chung, mọi thứ đều có nguyên tắc, tuân thủ theo luật lệ sẽ cho ra các sản phẩm unit-test chất lượng.

Nếu ai đủ kiên nhẫn đọc đến đây thì sẽ thắc mắc, viết dông dài vậy làm gì. Ah, tất nhiên là mình giới thiệu sách rồi (thực ra là khoe cuốn sách mới mua, mới đọc được có cái (hard)cover và cái preface đã bay lên chém gió như thần).

Tên cuốn sách
xUnit Test Patterns: Refactoring Test Code: Gerard Meszaros

Mục đích cuốn sách:
– Giải tỏa nỗi sợ về (automated) (unit) testing. Là nguồn cảm hứng và chỗ dựa (kỹ thuật) vô cùng bổ ích cho những ai đã, đang và sẽ có dự định improve productivity throuhg testing. Cuốn sách đề cập đến các kỹ thuật develop automated unit test case, các test smell để giúp programmer tránh các lỗi thường gặp lúc viết production code và test code + các cách refactoring chúng. Test principle là kim chỉ nam cho việc viết test, test design patterns là các practices áp dụng cho từng trường hợp cụ thể.
– Nếu xem GoF là kinh thánh cho dân Production Code thì xUnit Test Patterns này là dành cho Test Code.

For fun:
– (Khoe) Sách gốc hardcover $79.99. Dày 900 trang, nặng gãy tay :)))
– Người review trên tinh thần chém gió là chính chứ mới đọc được cái cover thôi =))
– Chỉ có cuốn sách trong hình là thật
– Link ebook cho dân không đủ điều kiện: google nhé 😉

Experience, OO Design Principles, TDD

Technical Debt và Legacy System

Technical debt – tạm dịch là “Khoản nợ kỹ thuật” được dùng nhiều trong Software Engineering. Theo Henrik Kniberg, những khoản nợ kỹ thuật là bất cứ thứ gì trong việc viết mã khiến bạn chậm lại về lâu dài. Ví dụ như là mã khó đọc, thiếu (hoặc không có) kiểm thử tự động, mã trùng lặp, hoặc sự liên kết lằng nhằng giữa lớp, mô-đun… (Think of technical debt as anything about your code that slows you down over the long term. Hard-to-read code, lack of test automation, duplication, tangled dependencies, etc. Henrik Kniberg).

cycle

Cũng giống như những khoản nợ về tài chính: có vay mới có nợ, có nợ ắt sẽ sinh lãi. Technical debt sinh ra vì nhiều lý do: áp lực kinh doanh, thiếu kỹ năng trong phân tích thiết kế cũng như kỹ năng lập trình, không có các bộ mã kiểm thử dẫn đến việc trì hoãn (hoặc không thể) tái cấu trúc lại mã nguồn… Nếu không được trả, theo thời gian, nợ sẽ đẻ lãi, dẫn đến việc chậm tiến độ, những đoạn mã mới được thêm vào sẽ mất nhiều thời gian và chi phí hơn, mà đa phần trong số đó là chi phí cho việc gỡ rối (debugging) và kiểm thử hồi quy (regression testing).

TechnicalDebt

Nếu bạn đang làm việc với 1 legacy system (có rất nhiều định nghĩa về legacy code, nhưng mình thích nhất định nghĩa của Robert C. Martin: legacy code = code without test) nghĩa là bạn đang mang trên mình món nợ về kỹ thuật. Một đoạn mã được viết cách đây 10 năm cũng gọi là legacy code, một đoạn mã được viết ngày hôm qua cũng gọi là legacy code nếu chúng đều không được “chống lưng” bằng mã kiểm thử. Và nếu bạn vẫn tiếp tục tạo ra những đoạn mã “without test”, cũng tức là bạn đang tự đẻ thêm nợ cho chính system của mình. Điều đó cũng giống như việc bạn thêm vào những đoạn mã khó đọc, mã trùng lặp, hoặc sự kiên kết lằng nhằng giữa lớp, mô-đun… (Có phải mình cũng vừa lặp lại những gì đã nói ở trên?).

Vậy bạn sẽ trả nợ bằng cách nào? Hay thõa hiệp trước món nợ + lãi đang ngày một tăng khi mã mới được thêm vào?
Có hàng tá lý do để biện minh cho việc thõa hiệp, có thể kể ra như: đừng phá vỡ những đoạn mã đã chạy ổn định, hệ thống chúng ta quá phức tạp, do đó cần thêm thời gian để (tìm hiểu) thêm mới hoặc sữa chữa một đoạn mã nào đó (và đảm bảo không phá vỡ những đoạn mã hiện tại). Có một câu ví von khá hay về vấn đề này. “The code may not be pretty, but damnit, it works!” dùng để nói về Duct Tap Programmer – người viết mã chỉ để “chạy được”.
Nếu chọn cách trả nợ, những việc bạn sẽ làm là đừng (hoặc hạn chế) để lại nợ nần cho những thế hệ (mã) phía sau. Và điều đầu tiên đó là Hãy ngừng việc tạo ra những đoạn mã xấu (Stop writing crappy code).

TechnicalDebt-StopWritingCrap-vs-KeepWritingCrap

TDD đã khó, TDD cho legacy system còn khó gấp bội. Bài viết dưới đây của Mark Levison bàn về việc những vấn đề gặp phải khi áp dụng TDD trong Legacy System, qua đó trích dẫn 1 số phương pháp của Keith Ray – XP Coach để làm việc với legacy code nhằm giảm (paying down) những khoản technical debt, dựa trên nền tảng cốt lõi là viết mã sạch, tái cấu trúc mã nguồn và bỏ túi SOLID principles.

Xin trích dẫn nguyên văn bài viết bởi Mark Levison từ http://www.infoq.com/news/2009/11/legacy-code

Allan Baljeu was trying to TDD with a legacy C++ code base, he was running into trouble because:

we end up with classes that don’t fully implement the functionality that’s eventually needed, and when others come around to use those classes, and eventually fuller implementations are required, then it turns out that the original design is not adequate, a new design is required, some expectations (tests) need to change and previous uses of the class need to be updated.

He wondered if Big Design Up Front would help solve the problem. George Dinwiddie, Agile Coach, suggested that Alan’s design was trying to tell him something. You have to pay attention to the fundamentals of clean code. You can look at basic coupling and cohesion (i.e. SOLID).

Mike “Geepaw” Hill, Agile Coach, says that in his years of coaching agile teams, one of the following has been at the root of these problems:

  • team is not yet up to speed on refactoring, so your classes aren’t really
    minimal
  • team is not yet skilled at simplicity, so ditto
  • team is not yet doing aggressive & rapid microtesting (aka unit testing), so changes break tests too often
  • team doesn’t know how to handle cross-team or company-to-public dependencies, e.g. shipping api’s
  • team neither pairing nor open workspacing, dramatically slowing team-wide understanding.
  • team likely has no jiggle-less build
  • team could be using tools from the ’40s

Keith Ray, XP Coach, suggests that with legacy code (i.e. systems with high technical debt) the cost of repaying technical debt dominates the cost of implementing a story. He goes on to offer an approach:

To make the code more well-factored (paying down the technical debt), whenever you need to integrate a new feature into it, you should pay close attention to code smells in both the new code and the old code and consider refactoring to deal with each smell as you recognize it.

You can do refactorings in small safe steps (even in C++) manually. Very closely follow the instructions in Fowler’s book on Refactoring until you learn them by heart. Eclipse with gcc has a few refactorings that actually work: Extract Method and Rename. Rename understands scope, so it is safer than search-and-replace. Extract Method and the other refactorings in Ecipse might be buggy, so be careful when you use them. For things like changing a function signature, “lean on the compiler” to show where changes have to be made.

You also need tests to make sure the refactorings are not damaging the existing features. Feather’s book on working with legacy code has lots of techniques for adding tests to legacy code. On a higher level, code smells are violations of good design principles. For example, the Single Responsibility Principle (SRP) says there should one purpose for every class / method / module. There are principles about coupling and cohesion and managing dependencies, etc. It’s often easier to detect a code smell than it is to apply these abstract principles. “Large Class” and “Large Method” are remedied by “Extract Class” and “Extract Method/Move Method”, though knowing SRP helps in deciding what parts of a class or method should be extracted.

Perhaps the most important design principle is “Tell, don’t ask”: keep functionality and data together…. bad code often has the functionality in one place, and gets the data it needs from other places, creating problems with dependencies and lack of locality — symptomized by “adding a new feature requires changing lots of code”. The code smells “Shotgun Surgery”, “Feature Envy”, “Long Parameter List” are applicable here.

Getting fast feedback will allow more refactoring, which will (eventually) allow faster development of new features. Try to get parallel builds happening (distributed compilation). Try to get smaller source files and smaller header files. Reduce the complexity of header files – use forward declarations, avoid inline code, try to keep only one class per header file / source file. Using the “pimpl” idiom widely can decrease compile time by 10%, but it can also disguise the “Large Class” and “Feature Envy” code smells.

The advantage of refactoring instead of rewriting, is that you always have working code. If your manual and automated tests are good, then you should be able to ship the code, even if it is a half-way state between a bad design and a good design.

Keith also wrote “Refactoring: Small Steps Guaranteed to Help You Clean Up Your Code” an article on refactoring C++ code in Better Software Magazine.

Previously on InfoQ: Dealing with Legacy Code, Uncle Bob On The Applicability Of TDD andMaking TDD Stick: Problems and Solutions for Adopters

TDD

What does TDD mean?

From http://blog.goyello.com/2011/08/29/what-does-tdd-mean/

Pawel Olesiejuk

 

Test Driven Development (TDD) is not about writing tests. Writing tests is writing tests, period. TDD is more than that, it’s a methodology.  It has started as a part of the agile methodology invented by Ken Beck called eXtreme Programming (we recommend Kent Beck’s book “Extreme Programming Explained”). The main idea of TDD is to write tests before code. It’s seems to be irrational but it’s not!

I try to do TDD every time when I’m writing code, but I won’t name myself a TDD expert. Experts like Robert C. Martin a.k.a. Uncle Bob, Kent Beck, Roy Osherove, Corey Haines and my teacher Kristoph Manuszewski, just to name a few, inspired me.

I’d like to share my knowledge about TDD and I’ll refer to articles/posts/books/screencast of people mentioned above.

It’s so f… simple

Most programmers can’t understand ‘Why the hell should I write a test for all code that I’m writing? It is so f… simple‘. Maybe it is, maybe it isn’t, but you can’t be sure that in the future the code remains the same. Edward V Berard says that ‘Walking on water and developing software from a specification are easy, if both are frozen’. Requirements are changing all the time, the environment is no longer stable. Perhaps someone else will extend/change your code. He is not you and he doesn’t know all the tricks you’ve used in your code. He can easily break your code without knowing it. This “he” could even be you after a couple of months.

Benefits of using TDD

It is proven that using TDD reduces the amount of bugs by at least 50% (The Cost of a Bug). I mean good TDD, not only automated tests. Consider this, how long does finding a bug take (and what about when an end-user finds it)? How long does tracing and fixing the bug take? How long do you need for integration tests to confirm you haven’t broken anything after fixing a bug?

Let’s assume the above will take 15 minutes to 3 hours per bug. How many bugs can there be in a single project? 100? 1000? So how much time do you spend on fixing them? This can easily grow up to 1,5h * 1000 = 1500h. Are you still there?

What would you say if you can save 750h in your project when using TDD? I think it is worth trying.

Tests are your safety net

Good tests (later on I’ll use “tests” for “good tests”) assure you that you haven’t broken anything in your previous functionality. This is the first (but not the only one) reason why you must (SIC!) write a test for every production code (production code is everything but tests) based functionality. If you have a code coverage of over 90% you will have certainty your code works. You won’t have to run the application to know that. This is your ‘safety net’, your parachute. Your tests should be as trustworthy as a net or a parachute.

Test driven code shows the user standpoint

When you write a test before writing production code you’ll understand how you (or somebody else) will use it, because the test is the first user of your code. And when you think from a user’s standpoint you will think about the interface first. This is a good design practice. Your code will be easy to use. It will become self explanatory.

Test Driven Design forces you to think upfront

Often after creating some class, you want to use it in another place and then you realize it cannot be reused in an easy way. It’s great and does lots of beautiful things at once. But it isn’t sufficiently useful. It isn’t flexible enough. It isn’t configurable, because you didn’t think of such things before.

If you’d written tests before you’d know about this stuff earlier and wrote this class in a different way. This is the greatest benefit of TDD!

Really, try it!

Usage specification better than documentation

Another advantage of tests is when someone reads them he’ll know how to use your code. Tests are like specification. Even better, they are usage specification, a tutorial ‘how to use the code’. Imagine that you are starting to use a new tool. With the tool you’ve got fat documentation with code samples on the back. What do you read first, API documentation or code samples? Furthermore, tests and code will always be in sync, so you don’t have to bother with synchronizing your documentation while the code is changing.

S.O.L.I.D. principles become natural

The next thing about writing tests before production code is that you won’t create big complex classes, because you really don’t want to write a complex test with lots of stubs. So, you will create small classes with only one responsibility. Your code will be decoupled, flexible and configurable. You don’t have to worry about S.O.L.I.D. principles. It will be so natural to follow them.

The proof of the pudding ….

In the end the proof of the pudding is in the eating. Therefor, to convince you probably the best example is a ‘real’ example. Robert C. Martin wrote series of articles about a young person (after school) who wants to become a programmer. But he didn’t want to write tests because he ‘can do this right without tests. It is so f… simple‘. I really recommend reading the whole story! You will find it here: http://www.objectmentor.com/resources/publishedArticles.html -> By Topic -> Craftsman

Test Driven Development gives you the opportunity to create well designed, flexible and easy to use code, good dependency decoupling and specification at once. Saying that writing tests before code costs you too much time is senseless. Redesigning, rewriting, debugging and creating specifications takes much more time. Furthermore, tests can assure you that your code (always) works, this is a priceless thing and nothing but automatic tests can give you such certainty. So… DO TDD!!