22 February 2026

BreakPointLocator: The Pattern That Can Save Your Team Weeks of Work

When debugging or extending functionality, there are many possible entry points:
  • Ask a coworker
  • Search the codebase
  • Google it
  • Trial and error
  • Step-by-step debugging
  • "Debug sniping" - pause the program at the 'right' time and hope you’ve stopped at a useful place
Over time, one of the most versatile solutions I’ve found is to use an enum that provides domain‑specific spaces for breakpoints.
public enum BreakPointLocator { ToJson { @Override public void locate() { • doNothing(); } @Override public <T> T locate(T input) { • return input; } }, SqlQuery { @Override public void locate() { doNothing(); } @Override public <T> T locate(T input) { // Example: inspect or log SQL query before execution if (input instanceof String) { String sql = (String) input; if (sql.contains("UserTable")){ • System.out.println("Executing SQL: " + sql); } } return input; } }, SqlResult { @Override public void locate() { doNothing(); } @Override public <T> T locate(T input) { return input; } }, ValidationError { @Override public void locate() { doNothing(); } @Override public <T> T locate(T input) { return input; } }, Exception { @Override public void locate() { doNothing(); } @Override public <T> T locate(T input) { return input; } }, ; public abstract void locate(); public abstract <T> T locate(T input); // Optional method for computation-heavy debugging // Don't include it by default. // supplier.get() should never be called by default public <T> java.util.function.Supplier<T> locate(java.util.function.Supplier<T> supplier); public static void doNothing() { /* intentionally empty */ } }

Binding:
public String buildJson(Object data) { BreakPointLocator.ToJson.locate(data); String json = toJson(data); // your existing JSON conversion return json; } public <T> T executeSqlQuery(String sql, Class<T> resultType) { BreakPointLocator.SqlQuery.locate(sql); T result = runQuery(sql, resultType); return result; }
Steps:
  • Each time that we identify a useful debug point, or logic location that is time consuming, we can add new element to BreakPointLocator or use existing one.
  • When we have multiple project, we can extend naming convention to BreakPointLocator4${ProjectName}.
  • Debug logic is for us to change, including runtime.
Gains:
The value of this solution is directly proportional to project complexity, the amount of conventions and frameworks in the company, as well as the specialization of developers.
  • New blood can became fluent in legacy systems much faster.
  • We have a much higher chance of changing service code without breaking program state while debugging (most changes would be are localized to the enum).
  • We are able to connect breakpoints & code & runtime in one coherent mechanism.
  • Greatly reducting hot swapping fail rate.
  • All control goes through breakpoints, so there is no need to introduce an additional control layer(like switches that needs controll).
  • Debug logic can be shared and reused if needed.
  • This separate layer protects us from accidentally re‑run business logic and corrupting the data.
  • We don’t need to copy‑paste code into multiple breakpoints.
  • The risk of mixing debug and business logic is greatly reduced.

0 comments / komentarz(y):

Post a Comment