At Phase 2, we not only value writing great software but also managing and delivering that software as efficiently as possible. As a software developer, if I could I would just write code all day and not think about much else. However, when writing production-ready code, the actual writing of the code is just one piece of the bigger pie. An efficient, stable, and dependable release pipeline allows us to focus more time on developing new features. It reduces the...

Espresso is a user interface testing kit that allows Android developers to simulate user interactions with their application and verify the results of those interactions. This kit helps ensure your app's very basic regression testing functions without bothering a QA team. However, there is a much greater potential of running into flaky tests when writing integration or user interface tests.  Flaky tests pass or fail inconsistently. Flaky tests exist because the test design contains something not accounted for. It isn’t always...

The inclusion of Phase 2 in Inc. magazine’s Best Workplaces list this year is a reflection of the company culture that we’ve fostered over 20 years. The saying, "your people are your most important asset" is somewhat of a cliché. But it doesn’t make it any less true. This is even more important in a services business where the effort and talent of our team creates what our customers buy.  Anyone in business will tell you that finding and retaining great...

A Client Guide from Our President/COO Heath Clinton If you or your organization is considering custom software as a solution to further your business, you may not know where to start. You may not know exactly what you need. That’s okay. In my role as Phase 2’s president and COO, I’ve seen what works and what doesn’t from both the client-side and the developer-side. I want to share what the client or organization might want to know - and quite frankly,...

Most experienced developers are familiar with using dynamic proxies. They enable us to implement an interface at runtime and decide how to execute methods dynamically as they are invoked. This is very useful to add additional functionality around existing implementations (especially from third-party libraries) as described by the Decorator Pattern. However, Kotlin coroutines introduce a new set of problems when creating dynamic proxies. We'll explore how to properly detect and dynamically invoke suspend functions declared on an interface. The Setup First, create...