The Problem's Knowledge

Posted by Jake Corn on November 25, 2019

I drove home from work the other day thinking about Table Driven Methods. (I need new CDs). I first learned about them from the book Code Complete by Steve McConnell.

for a little context about Table Driven Methods....

(if you don't mind my paraphrase) A Table Driven Method is a strategy by which a problem's knowledge is coded in data rather than an if/else scheme. In other words its a different way to handle conditionality

Though useful and interesting what struck me most the notion of a "Problem's Knowledge". I never realized problems knew about anything.

But they do. They know exactly what they need to not be problems anymore. When the essential part of a problem is understood a solution can be formed.

What about Solutions? What should they know?

Solutions should know as little as possible to solve the problems they are given. Solutions have their own problem.

In Code...

Imagine a rest endpoint

GET('/posts' () => {
  //... from where?
  //... formatted like?
})

It solves a problem for someone calling it. It solves the problem of "Who do I call to get my posts?"

But it has its own problems.

GET('/posts', () => {
  //... from where? how do I get them
  //... formatted like? do I need to shape them for the caller
})

"Knowing" we have these problems let's look at the "From Where" portion. If we already have a db where we are storing things we might create a new table

create table Posts (
  id int not null,
  title varchar(100) not null,
  content varchar(max) not null,
  author varchar(100) not null,
  primary key (id)
)

then in a service

PostService {
  all() {
    return Post.find({ where: {/* map of predicates */}})
  }
}

It could look something like the above.

or it could look something like this

PostService {
  all() {
    return query('select id, title, content, author from Posts where ...')
  }
}

What difference does it make and which one to choose if it all evaluates to posts for our user?

Back to the essential... What is needed to solve the users problem of not seeing posts?

Does the user need the PostModel? What value does it provide? Does your controller need that dependency? What about "query"? Is that something your controller needs to rely upon?

The answer is found in answering another question? Which one is easier to implement? Would your controller rather rely on PostModel or query?

Chances are that you are relying on query either way (PostModel needs some way of querying). This is called a Transitive Dependency.

By reducing transitive dependencies you have reduce the risk of volatile code changes as any changes to PostModel (which is an object with methods) has a risk of changing your controller. Assuming PostModel relies on query anyway, the volatility risk is vastly lower by dependending only on the query function.

This can be applied to all the problems of the controller. What about the problem of formatting i would ask is this an acceptable format?

{ title, content, author }

If so, that is one less thing our solution provides. no Formatter class etc... The database already reveals that. If they need to be in some format, can the user be the one to do the formatting? Asking these questions is important.

In other words, solutions should be minimal. Problems tell us most of what we need to know in order to solve them. When I need a coffee I am not forced to hear about the packaging or the region it comes from, I am simply given a coffee. Coffee solutions are almost always more correct (especially since they satisfy angry addicts like myself :)

Solutions should know about the problem's knowledge and only enough to make them not a problem anymore. Every time you sleep with a dependency, you sleep with all the dependencies it has ever slept with. Rely only on what is needed.

Require less, do more.

--jake