Configuration scripts - part 2

In Part 1 I described how my configuration script system works. Part 2 will focus more on the real reason why I decided to write this post:

Designing intuitive API that makes sense.

The more I code and work on complex systems the more I see how important good API is. There is of course 1001 articles describing how to do that and if you are searching for one of them you are not in the right place. 

My focus will be on my personal evolution in a way how I think about API. Whole thought came from improving compute shader scripts. They had a really simple form:
Compute
{
    Define("MY_DEFINE")
    Reg(0) = UserImage(0, "Write", 0)
    Reg(1) = UserTexture(4)
    Reg(2) = UserTexture(5)
    Reg(3) = UserTexture(6)
    Reg(4) = Texture("sys://Textures/Texture.dds")
    Reg(5) = UserTexture(7)
    ShaderFile =  "sys://Shaders/ComputeShader.glsl"
}
This was nice but defining N users texture registers felt pretty robust so in the past I have done my first improvement: 
Compute
{
    Define("MY_DEFINE")
    Reg(0) = UserImage(0, "Write", 0)
    Reg(1:4) = UserTexture(4)
    Reg(4) = Texture("sys://Textures/Texture.dds")
    Reg(5) = UserTexture(7)
    ShaderFile = "sys://Shaders/ComputeShader.glsl"
}
In this form, I was using a script for some time. Everything was "perfect" till I started to work on the next iteration of material scripts and decided to also improve compute shaders scripts. At this point for the first time, I really started to think what I like and dislike in this format.

What I like:

  • Script doing what it should.
  • I like the possibility of working on multiple registers (this saves a lot of time).
What I did not like:

  • API feels inconsistent. 
  • Working on multiple registers is not really intuitive.

Problem

What irritated me the most was the point "Working on multiple registers is counterintuitive.".
  1. Reg(1:4) = UserTexture(4) 
  2. Reg(5) = UserTexture(7) 
Why line 1. expands into:

    Reg(1) = UserTexture(4)
    Reg(2) = UserTexture(5)
    Reg(3) = UserTexture(6)

Where line 2. is untouched? How I can assign the same user texture to the same register? At this moment my thoughts started drifting and I started thinking about API in general and my past experience.

We, programmers, love to write API (especially new ones). When we do it we thinking what new piece of code should do. When we expanding existing API we modify it by adding functionality we need to continue our work. We take pride in the systems that we designing and code that we wrote. These are awesome pieces of technology that push industry forward.

This, of course, applies only to our code. The Code of others is mostly to rewrite. It not necessarily doing what it should and even if it does, we could do it better.

In the end, this is a really dangerous way of thinking.

This is a trap

The code is just a code. Depending on your skills, background, experience, language you use or just how long your code you may see a different piece of code as a good one. That is why it is important to analyze the existing piece of code not only in terms of how it looks right now but also reasoning and intention behind it.

Sometimes you may be surprised that code that looks bizarre is this way because it couldn't be done a lot better without major refactoring which could endanger the shipment. Another possibility is that it touching such a critical code path that it would take too long to fix it. I have seen also code that became worse when somebody started modifying code without fully understanding its intention. There is, of course, the possibility that code is just bad but while working with experienced people you should put this option at the end of the list.

While you should trying to not judge the code of others to fast, you should also be open for comments from other coders. If somebody criticizes your code don't be an asshole, sit silently and later badmouth them behind their back. Approach them and start a discussion about the reason they think this code is bad. Maybe they are right and this code could be done better and you will learn something new. Maybe they just missing context or doing some wrong assumptions and after your explanation, they will know more and see this code a little bit differently.

In the end, everything falls into the topic I discussed in  Code review story ... if you don't want to throw away your pride and start a constructive discussion you will never improve.




When I started doing part 2 I didn't expect this topic to have part 3 but well surprise surprise. This feels like right place to have another split. In the last part, I will discuss how I changed my compute shader script and try to explain why I did it in the way I did.

To next time.
Greg



Comments

Popular posts from this blog

Query commands execution

Hierarchy - UI improvement

Singleton pattern