Discriminants are Stinky

November 4th, 2023

I recently came across the suggestion of implementing a ColorValue type that uses an enum field to differentiate different color spaces that can be represented in C# as the following:

enum ColorSpace
{
  Cmyk,
  Rgb,
  CieLab
}

class ColorValue
{
  public ColorSpace ColorSpace { get; init; }
  public double[]? Component { get; init; }
}

The above concept has been used for discriminated unions found in C code when unions were introduced to the language in 19731. Bjarne Stroustrup finds weakness in this approach when discussing “type fields” as he calls them2:

Any addition of a new kind of [type] involves a change to all the key functions in the system — the ones containing the tests on the type field. The programmer must consider every function that could conceivably need a test on the type field after a change. […] In other words, use of a type field is an error-prone technique that leads to maintenance problems. The problems increase in severity as the size of the program increases because the user of a type field causes a violation of the ideals of modularity and data hiding. (310)

Although Stroustrup goes on to talk about moving away from “type fields” towards C++’s derived types and polymorphism, software engineering concepts have been debated and evolved through the decades since Stroustrup provided methods of localizing implementation knowledge to specific types. Compilers have also since been updated to report when an enum value is not handled in a switch statement.

The use of discriminants or “type fields” is a stinky code smell, because it potentially violates the open-closed principle, which Robert C. Martin presented around the time Stroustrup’s book was published and remains popular today. The issue can be exemplified with the following function:

void MyFunctionA(ColorValue v)
{
  switch(v.ColorSpace)
  {
    case ColorSpace.Cmyk:
      // handle CMYK ColorValue
      break;
    case ColorSpace.Rgb:
      // handle RGB ColorValue
      break;
    default:
      throw new ApplicationException();
  }
}

Now, imagine that there are tens or hundreds of similar functions that examine the ColorSpace field before performing operations that are specific for a particular type. Each of these functions would need to be reviewed or updated when a new ColorSpace, such as CIEXYZ, is introduced. These functions need to remain open for modification when functionality is extended.

Refactoring toward an implementation consistent with SOLID principles might include grouping these functions into interfaces. Then, new classes can be introduced that implement these interfaces to operate with new types of color space objects, such as those of type ColorCieXyz.

References

  1. History of C – cppreference.com
  2. Stroustrup, Bjarne. The C++ Programming Language. Addison-Wesley, 1997.

SOLID: Design Principles and Design Patterns

November 1st, 2023

In Design Principles and Design Patterns, Robert C. Martin presented the SOLID principles of object-oriented software design over twenty years ago. “SOLID” continues to be a buzzword included in many resumes today. The principles are reproduced here:

  • A class should have only one reason to change.
  • A module should be open for extension but closed for modification.
  • Subclasses should be substitutable for their base classes.
  • Depend upon abstractions. Do not depend upon concretions.
  • Many client-specific interfaces are better than one general purpose interface.

Developing SOLID software is developing software that consists of minimalist components with well-defined abstractions or interfaces that are resistant to software rot caused by requirements changes.

Martin’s original paper includes a draft bibliography. Software engineers looking for additional reading may be interested in the bibliography’s “OOSC98” entry, which likely refers to Bertrand Meyer’s Object-Oriented Software Construction. It is made available by the author, reserving all copyrights, including the rights to distribution.

Processor Upgrade: AMD Ryzen 7 5800X3D

September 27th, 2023

After forty months, I upgraded my personal desktop processor from AMD Ryzen 5 3600X to AMD Ryzen 7 5800X3D. I also installed an NZXT Kraken 280, which fits snugly in an NZXT H510i as the image below shows. CPU temps get as low as around 38°C and peak at around 90°C with an ambient temperature of 23°C. Microsoft Flight Simulator 2020 runs at 1% CPU while my AMD Radeon RX 5700 XT is the bottleneck running at 100%. I get 30FPS with Ultra settings on a 1080p.

I gain two cores but lose memory speed with the upgrade. The system should be good enough for the next round of video cards. I am only slightly satisfied with the processor and cooling system refresh.

Ruby Switch

July 12th, 2023

Ruby Switch is a web browser plugin that I developed to make toggling the visibility of ruby text such as furigana more convenient. To further my study of the Japanese language, I frequently visit Internet sites for language learners or young native speakers. These sites typically show how vocabulary using kanji is read. Sites, such as NHK‘s site, feature news written in simple Japanese and make it easy to toggle between showing or hiding how to read kanji. Other sites do not offer that feature, and toggling ruby text requires going into a web browser’s development tools to modify the CSS.

The following image shows Ruby Switch pinned to the Mozilla Firefox toolbar and renderings with and without ruby text of a page on Mainichi Newspaper for elementary school students.

Ruby Switch allows practice in reading Japanese. This simple plugin allows language learners to conveniently toggle the visibility of furigana to allow reinforcing vocabulary that is recognizable while also allowing them to confirm their readings when there is uncertainty.

The following is a sampling of sites that work with Ruby Switch:

Two Years with WaniKani

May 13th, 2023
Posted in 日本語 | No Comments

After almost two decades after taking two years of college classes on the Japanese language, I have been using for the last two years a tool that is helping me overcome a major obstacle on the path toward language proficiency. Up until this second anniversary, WaniKani has helped me recognize and read more than 2,657 words composed of kanji.

It has taken me about two years to reach level 45 out of 60 offered by WaniKani. I did not expect to experience burnout, but I did at levels 20 through 23. I needed more than half a year, or 25% of my time with WaniKani, for just those four levels. If I maintain an average of 17 days per level going forward, I will have been exposed to all review items in eight months. It is possible to rush through the last 15 levels in four months, but my experience with burnout is encouraging me to enjoy the process and continue at a moderate pace.

I am pleased with my accuracy and the balance of items between various SRS stages. A review item requires six months to transition from “enlightened” to “burned.” To become burned, an enlightened review item’s meaning and reading must be remembered correctly after it has not been reviewed for six months. A review item is demoted to a lower SRS stage, if it is not remembered correctly. In theory, 3,773 burned items have become part of my long-term memory. Remembering these items is reinforced by studying higher level textbooks and consuming native material. For example, music videos for anime songs provide lyrics containing kanji. Reading anime song lyrics reinforces my ability to recognize and read those kanji.

WaniKani has made studying intermediate textbooks and consuming native material more enjoyable for me. Less time is spent looking up common words in a dictionary. This has allowed me to focus on the actual content of the media. I have no regrets signing up for a lifetime WaniKani membership, and I recommend it to anyone interested in learning Japanese.