Non-developer often imagine developer as people who just write code. Actually, some developers also imagine themselves as people who just write code. The point is that a person that just write code is not a developer. It is a coder. Nowadays, developers are no more that neardy guy writing strange symbols on its computer, and we no more measure competency of a developer by its ability to write cryptic ultra-optimized code. Developers have to understand the perimeter of their application, they have to discuss with PO, with stakeholders, with customers to understand their needs, they have to deal with technical choices, architectural concerns and take long term decisions. And must of all, developers have to deal with other developers.
Lets have a look to the same code written by a coder and a developer. A simple Color class to handle red, green, blue and alpha channels.
//
// Color.h
//
class Color {
public:
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
: m_r(r)
, m_g(g)
, m_b(b)
, m_a(a)
{}
Color(float r, float g, float b, float a)
: m_r(r*255.f)
, m_g(g*255.f)
, m_b(b*255.f)
, m_a(a)
{}
float at(int index);
private:
uint8_t m_r = 0;
uint8_t m_g = 0;
uint8_t m_b = 0;
uint8_t m_a = 0;
};
And now the same code written by a developer. See how the implementation code is rigorously the same.
//
// Color.h
//
/** Small class to manage Color.
* Warning: this class is not thread safe. */
class Color {
public:
/** Create a color form red, green, blue and alpha values */
Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
: m_r(r)
, m_g(g)
, m_b(b)
, m_a(a)
{}
/** Create a color form red, green, blue and alpha values.
* r, g and b must be in [0.0, 1.0].
* a must be in [0.0, 255.0] */
Color(float r, float g, float b, float a)
: m_r(r*255.f)
, m_g(g*255.f)
, m_b(b*255.f)
// WARNING: 20 years ago, someone forgot to multiply by 255.
// this error came to production and now every other
// libraries and all our customers are based on this
// behavior.
// DO NOT renormalize by 255 here as it will made a LOT
// of people grumpy.
// See ticket TIC-542 for details.
, m_a(a)
{}
/** Convenient method to get color from id:
* 0=>red, 1=>green, 2=>blue, 3=>alpha.
* Throw outOfRange exception (in DEBUG only for perf reasons)
* if index is not in [0, 3]. */
float at(int index);
private:
uint8_t m_r = 0;
uint8_t m_g = 0;
uint8_t m_b = 0;
uint8_t m_a = 0;
};
//
// Color_test.cpp
//
TEST(ColorShould, instanciate_black_from_utint8)
{
Color black(0, 0, 0, 0);
EXPECT_EQ(black.at(0), 0);
EXPECT_EQ(black.at(1), 0);
EXPECT_EQ(black.at(2), 0);
EXPECT_EQ(black.at(3), 0);
}
// [...]
// Lots of other unit tests
// [...]
TEST(ColorShould, not_normalize_alpha_TIC_542)
{
Color white(1.0, 1.0, 1.0, 1.0);
EXPECT_EQ(white.at(0), 255);
EXPECT_EQ(white.at(1), 255);
EXPECT_EQ(white.at(2), 255);
EXPECT_EQ(white.at(3), 1);
}
One can see several differences.
First, developer care about its future users. He write documentations, and not only obvious one. He describe error case and things that are not obvious in method signature, like differences between DEBUG and RELEASE for the at() method.
Second, developer care about existing users. He know its code is used by many other people and any modification may have a lot of impact. Even when there is an obvious bug, like the alpha normalization in 2nd constructor. He also enforce this behavior compatibility by writing unit tests.
Last but not least, developer care about other developers. In this case, he clearly state that the missing *255.0 is voluntary, so that its colleagues won’t be tempted to change this line and loose time running failed unit test.
Off course, being a developer is much more than just adding comment line in code. But it is the mindset of caring about others that make the difference between coding and developing.
Leave a Reply