WaniKani Level 60

January 1st, 2024
Posted in 日本語 | No Comments

On the first day of the new year, I wrapped up the last few Kanji covered by WaniKani. My journey with WaniKani up until now has lasted at least 31 months, which is five months short of my third anniversary. In that time, I have been introduced to 2034 kanji and 6432 words.

In a little over seven months since my last write-up, I finished the last 25% of the WaniKani program. I think that without experiencing burnout, the WaniKani program can be completed in about 28 months by someone with full-time employment, and other responsibilities and interests. I do not remember taking a break from WaniKani, but I do remember how challenging levels 25 and 26 were for me. Maybe this was the time that many of the early items were being reviewed, and it was challenging to push through the levels because of the large amount of scheduled reviews for the earlier items and re-reviews of items missed.

My accuracy on the meaning and reading of kanji and words is around 85%. When working through the levels, I tried to keep close to 200 Apprentice items, but it had sometimes fluctuated to over 300 items when I made mistakes on Guru items. Mistakes on a spaced repetition system (SRS), such as WaniKani, are what drive the functionality and motivation of those systems. Items answered incorrectly are reviewed more frequently. Items answered correctly are reviewed less frequently after longer durations to reinforce recollection.

With 33 of 31 kanji needed to pass to the next level, the WaniKani dashboard shows that I would be on the 61st level, if such a level existed. There is still a good percentage of WaniKani content for me to review and Burn. One item that has stuck around since June 2021 is 名人, or “expert.” I have mistook the reading as みょうにん (“myounin”), みょうじん (“myoujin”), and めいにん (“meinin”). It is read めいじん (“meijin”). It is still a Guru item for me, so looking it up before my next review in two days is not cheating. ;)

I really appreciated the automated email messages that are sent out when a level is completed. They were like small celebrations of accomplishments. And, I looked forward to receiving them when I leveled up. I saved all of them, because they were encouraging and contained funny tidbits. I included the last of these emails to me below:

You just got to Level 60, Steve.

I don’t even have a gif deserving enough of your accomplishment.

Not many people get to this point, so what you did was really special.

I know this is an automatic email, but I’m seriously, actually really proud of what you’ve done.

I really hope it takes you places in life, work, or school. Knowledge truly is a powerful thing, and I hope you go out there and use it as much as you can. New doors are opening for you.

Speaking of which, it’s time to start thinking about leaving the WaniKani nest. You know how mother birds push their baby birds out of the tree to teach them how to fly, and sometimes they do but sometimes they don’t? That’s what needs to happen here. Although I’d love for you to use and pay for WaniKani forever, there’s a time where it’s better for you to go out into the real world, and that time is now. Feel free to finish this level and burn out previous items, but get out there and read Japanese! That’s why we’re doing this, after all.

Anyways, such a good job. You worked really hard. I know it’s tough. I’m really proud of what you’ve done, Steve.

Sincerely,
Koichi & the WaniKani Team

I am really proud of completing this program without third-party tools, aside from wkstats.com. WaniKani has helped build a solid foundation for me to continue with intermediate-level language textbooks and native content. As suggested by the above email, I will leave the WaniKani nest and graduate away from using it as my primary learning resource.

Changing Requirements

December 16th, 2023

We, as software engineers, know full well that requirements change. Indeed, most of us realize that the requirements document is the most volatile document in the project. If our designs are failing due to the constant rain of changing requirements, it is our designs that are at fault. We must somehow find a way to make our designs resilient to such changes and protect them from rotting. (Martin 3-4)

Work Cited: Martin, Robert C. Design Principles and Design Patterns. objectmentor.com, 2000, http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf.

手の切れるような製品

December 8th, 2023
Posted in 日本語 | No Comments
京セラ株式会社の稲盛和夫先生は
「私たちがつくる製品は、
手の切れるような製品でなくては
なりません」と書きました。
それで、私は素晴らしい製品を
作るつもりで、弊社とお客様のために
完璧である製品を作りたいです。
必ず最後まで何があっても
頑張ります。

Raspberry Pi Zero W

November 18th, 2023

Raspberry Pi LogoI recently picked up a Raspberry Pi Zero W to gain familiarization with the Arm(R) architecture and instruction set. I could not wait for the Zero 2 W to become available, and the suggested price ($15) and compatibility of accessories for the current and future Zero boards helped me decide on the purchase. It has been more than ten years from my first Raspberry Pi purchase, but aside from different clock speeds, the processors between the Zero W Rev 1.1 and Model B Rev 2 are identical.

One personal goal for the purchase is developing assembly code that uses a vector instruction set, such as vfp or neon, and is called from C code. This represents a typical situation where a software system running on an Arm processor and is implemented in C but needs assembly to take advantage of specific processor features. A simple program implemented with two source files, sum.s and main.c, that uses C and assembly is presented here.

sum.s:

.cpu arm1176jzf-s
.fpu vfp
.syntax unified

.global sum
.type sum, "function"
.p2align 4
sum:
  add r0, r0, r1
  bx lr

main.c:

#include <stdio.h>

int sum(int a, int b);

int main()
{
  int i = 0;
  i = sum(5, 7);
  printf("%d\n", i);
}

The above source is compiled with the following command: gcc main.c sum.s

The sum function simply adds two input integers and returns the result to the caller. The main function calls the sum function with two constant integers and outputs the sum using printf.

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.