London vs Chicago

Adopting an integrated approach to TDD.

assistant Learn More
DevOps

Software Delivery
with Containers

Imagine deploying and running your applications and services in an environment that is fully-automated, self-healing, and scaled based on incoming demand, in the blink of an eye, on a footprint smaller than any virtual machine (VM) on the market.  Technology companies, such as Google, have been doing this for well over a decade.  This platform is called a container and it is the biggest revolution in DevOps to date.

subject Read Article
DevOps

Quantifying Software Quality

As software development teams look for ways to improve their products and services, they often look at improving time to market, better prediction of release schedules, improving customer satisfaction, and raising overall software quality.  Software “quality” can mean a lot of things to different people.  But quality goes way beyond how well a product functions or how many bugs it contains.

subject Read Article
DevOps

Managing Technical Debt

The manner in which technical debt is managed can give a company a competitive advantage when it’s most needed or destroy a well conceived product.  When incurred properly, technical debt can greatly decrease time to market, providing a short-term advantage over the competition.  But if that debt is not paid off quickly, it will slowly, yet surely, erode the quality and the value of your software.

subject Read Article
assistant Development Tip

Shift Left

Escalate the value of software systems by focusing on quality as far left within the Software Development Lifecycle (SDLC) as possible.  By creating quality at the source, we can identify problems as they occur, build new knowledge, and optimize for downstream work centers.  Quick feedback will promote quality and reliability within our value streams.  The sooner we identify defects, the easier, quicker, and cheaper we can fix them while greatly reducing risk.  Accelerate work flow by prioritizing Structural Quality as highly as user features and ensuring on-going Compliance with Non-Functional Requirements (NFRs).

Learn More
assistant Development Tip

Improving Design

Make it a habit to continuously improve the design of your software through refactoring and optimization.  Refactor your code to improve its Structural Quality and optimize your code to improve resource utilization.  If applied correctly, these techniques will enhance the quality of your software without affecting its behavior.  Remember to refactor your code before optimizing to make your software more adaptable to performance tuning.

Learn More
assistant Development Tip

Frequent Check-Ins

Promote a DevOps model for software delivery by checking code into the trunk multiple time each day.  This will ensure the changes are smaller and less likely to break the build, foster greater discipline in refactoring by preserving behavior through small changes, and ensure you can revert to a good, known version of the software when a mistake is made.  Avoid using branches as that will only delay the integration of code from other developers.  You cannot have Continuous Integration (CI) without frequent integration.  Otherwise, you’re promoting nothing more than CI Theatre.

Learn More
assistant Development Tip

Immobility

Avoid this design smell by building software from which it is easy to extract and reuse internal components in new environments.  This smell is often caused by dependencies that are tightly integrated with other parts of the system.  Promote mobility by decoupling components from low-level implementations, such as data persistence, logging, user interfaces, etc.  For example, business rules should be encapsulated within components to enable reuse across multiple systems.

Learn More
assistant Development Tip

Rigidity

Avoid this design smell by building software that is flexible and easy to change.  Rigidity is often observed when a small change forces a complete rebuild and redeploy.  Small changes should be able to be built, tested, and deployed very quickly and independently of each other.  Long build times are a symptom of high coupling.  To promote flexibility, manage the dependencies between modules to ensure when one module changes, the others remain unaffected.

Learn More
assistant Development Tip

Fragility

Avoid this design smell by building software that is highly modular, highly cohesive, and loosely coupled.  A change to one part of your system should never break another part that is completely unrelated.  High level policies (i.e. business rules) should never be impacted by changes to low level implementations (i.e. data persistence).  Even related functionality should be decoupled enough to extend functionality without affecting related components.  There are many engineering patterns and practices that facilitate flexibility, extensibility, adaptability, along with many other qualities that inhibit fragility.

Learn More
assistant Development Tip

Two Hats

As software is developed by making behavioral and structural changes, do not attempt to do both at the same time.  Wear one hat to add new capabilities (including tests) without changing existing code, then wear the other hat to restructure the code without changing behavior.  Build software by swapping hats frequently to develop and test very small capabilities, then refactor to improve the design and the overall quality of the code.

Learn More
assistant Development Tip

Software Evolution

Build your initial features quickly, then evolve your software based on customer feedback.  This demands having a good suite of tests to prevent cruft and promote refactoring without the fear of breaking those features.  This also requires being able to recognize design smells.  These smells will permeate your software due to bad decisions caused by carelessness and false expedience.  Manage the dependencies within your software to ensure a loosely coupled architecture and...

Learn More
assistant Development Tip

Slow Tests

Build your software and your tests in ways that minimize test execution time.  Common causes for long running tests include over-engineered test fixtures, asynchronous code, components with high latency, Test Overlap, and too many tests due to a tightly coupled architecture.  This causes bottlenecks in Continuous Integration, inhibits rapid feedback facilitated by automated testing, and constrains frequent code merges that are required for Trunk-Based Development.

Learn More
assistant Development Tip

I’ll Fix It Later

Do not fool yourself into thinking you will ever go back and actually rewrite your code the right way.  Any experienced developer will tell you it rarely happens (even with the best of intentions).  And every time you save that cruft for later, you’re introducing Technical Debt, which will do nothing but slow you down.  To go fast, you must go well.  Trading quality for velocity will catch up to you very quickly and slow you down much more than if you had written good code to start.  This does not mean you should...

Learn More
assistant Development Tip

Trunk-Based Development

Embrace continuous delivery by frequently integrating small batches of work directly into the source control trunk (at least once daily).  Short-lived branches can be used to implement pull requests or to isolate release candidates, but should never persist longer than a day.  Utilize Feature Toggles to turn off features that are not yet ready for release.  Pull the Andon Cord and fix regression errors immediately to keep the trunk in a healthy and deployable state.

Learn More
assistant Development Tip

Repeatable Tests

Write tests such that each produces the same result from a given initial state without any manual intervention between runs.  Unit tests must verify Single Test Conditions by executing a single code path through the System Under Test (SUT) and executing the same, exact code path each time it runs.  Verifying one condition for each test helps to minimize Test Overlap and ensures we have fewer tests to maintain if we later modify the SUT.  Isolating the SUT ensures that we only have to focus on code paths through a single object. 

Learn More
school Training

The Technical Discipline of Being Agile™

Agile was created by 17 technical leaders in the software industry who crafted a lightweight development process that was intended to heal the divide between business and developers.  They also established technical norms that would mitigate common issues such as excessive cruft, tightly coupled architectures, rigid code, immature test suites, technical debt, along with other anti-patterns that slowed delivery of high quality software.  This course examines the characteristics of good and bad software and explores technical practices that resolve the issues and enable teams to deliver great software fast.

Learn More schedule 6 Hours
school Training

Managing Technical Debt

To maintain business, market, and technological advantages, you must effectively manage technical debt incurred within all artifacts that define, implement, and validate your software.  This course examines what technical debt is, how it can benefit your organization and give you an advantage over your competition, how and when it should be (intentionally) incurred, and how and when it should be paid off.

Learn More schedule 2 Hours
school Training

Principles & Practices of Test-Driven Development

This course teaches the principles and practices of Test-Driven Development (TDD) and demonstrates how proper software design evolves through application of the eXtreme Programming principle of Test First.  Unit testing principles are introduced, along with a thorough discussion on the benefits of TDD.  An application is developed (from start to finish) during this course to explain step-by-step and demonstrate first-hand how a high quality, testable design evolves by applying the three laws of Test-Driven Development.

Learn More schedule 90 Minutes
computer Code Kata

Prime Transformation

A good TDD developer is one who can apply transformations well.  What are transformations?  They are the opposite of refactoring.  While refactoring is changing the structure of code without changing its behavior, transformations are changes to code that generalize behavior without changing its structure.  In this kata, you will create a function to calculate the prime factors of a given integer using TDD while applying transformations to pass the tests.

Get Started

Doug Klugh

Software Craftsman

Software Development and DevOps Leader, Microsoft developer, and Agile Coach.

;