Skip to main content

· 3 min read

“Smells,” you say, “and that is supposed to be better than vague aesthetics?” Well, yes. We have looked at lots of code, written for projects that span the gamut from wildly successful to nearly dead. In doing so, we have learned to look for certain structures in the code that suggest—sometimes, scream for—the possibility of refactoring.

  • Kent Beck and Martin Fowler, Refactoring

Code smell is a term used to describe the tell-tail signs of bad software and therefore an indication that refactoring is overdue. Similar to design patterns that we learn to recognize and apply in our software, naming and identifying different code smells can help us triage the existing code base and proceed to apply fixes in the form of refactoring.

Below is a catalog of code smells identified by Martin Fowler

  • Alternative Classes with Different Interfaces
  • Comments
  • Data Class
  • Data Clumps
  • Divergent Change
  • Duplicated Code
  • Feature Envy
  • Global Data
  • Insider Trading
  • Large Class
  • Lazy Element
  • Long Function
  • Long Parameter List
  • Loops
  • Message Chains
  • Middle Man
  • Mutable Data
  • Mysterious Name
  • Primitive Obsession
  • Refused Bequest
  • Repeated Switches
  • Shotgun Surgery
  • Speculative Generality
  • Temporary Field

A Practical Example: Comments

Comments are helpful when used to make clarifications and explain the purpose of the code. However, comments are also tricky to write because when done poorly, they can be a source of noise and potentially exposed the weakness in software. On top of the techniques of writing good comments, let's take a look at how comments can become code smells that prompt us to refactor.

Comments that describe what a function does

// add expenditure to record
void processInput(int data) {
//...
}

Course of action: Rename function and remove comment

void recordExpenditure(int amount) {
//...
}

Comments that describe what a block of code does

static Command parseInput(String input) throws InvalidInputException {
String task = Parser.tokenize(input)[0];
// check if the user input contains recognized keywords
boolean hasKeyword = Arrays
.stream(TaskType.values())
.map(TaskType::getRep)
.anyMatch(x -> x.equals(task));
if (!hasKeyword) {
return false;
}
return Parser.interpret(input);
}

Course of action: Extract function

private static boolean hasTaskKeyword(String input) {
String task = Parser.tokenize(input)[0];
return Arrays
.stream(TaskType.values())
.map(TaskType::getRep)
.anyMatch(x -> x.equals(task));
}

static Command parseInput(String input) throws InvalidInputException {
if (!hasTaskKeyword(input)) {
throw new InvalidInputException(input);
}
return Parser.interpret(input);
}

Comments that describe assumptions

public ShowCommand(Index index) {
// note that index must not be null!
// and index must be larger or equal to zero!
this.index = index;
}

Course of action: Be defensive & use assertions

public ShowCommand(Index index) {
requireNonNull(index);
assert index.getZeroBased() >= 0;
this.index = index;
}

Further reading

· 3 min read
TLDR: You should watch this video by Stuart Marks if you wish to learn more about the considerations behind Java's Optional feature and its practical usage.

Motivation

I was introduced to Java's Optional as a response to the billion-dollar mistake made by Tony Hoare, the little monster called "null".

Tony Hoare introduced Null references in ALGOL W back in 1965 "simply because it was so easy to implement", says Mr. Hoare. He talks about that decision considering it "my billion-dollar mistake".

Honestly, I had never considered null as the problematic kid on the block. If there were any thoughts as a Java beginner, I felt that null was extremely helpful in dealing with return types. No suitable object for a method to return? Just return null.

When I learned about Optional, I thought that it is an unnecessary abstraction. Why go through the trouble of boxing up an object and then pass the instructions to the box in order to interact with the value contained in the Optional? This is actually because of the problem of null reference and also issues with having null as a return value.

Problem with null reference

When methods calls are chained together, a method within the chain will cause the following method to throw an exception if it returns null.

methodA().methodB().methodC();
// if methodB returns null, it results in
// null.methodC()
// Not a good idea

The issue with this is that although we can proactively check for null references before invoking a method call, that solution will result in messy and necessarily long code just to ensure a method call is legitimate.

Foo foo = methodA();
if (foo != null) {
Bar bar = foo.methodB();
if (bar != null) {
Coo coo = bar.methodC();
}
}

Problem with the meaning of null

There might be cases where null is returned to signify an empty value. And there might be cases that null is returned to mean invalid. Therefore, it might be confusing to use it as a return type. This often means that the developer has to put in an extra effort to express his intent in the comment or in the documentation. The callers to such code also suffer from having to deal with such functions with care.

Solution provided by Optional

I choose to leave out the details of Optional API and its usage for now as I intend to cover it together with Java's Stream and CompletableFuture, drawing on their similarity of providing a context/abstraction. The details of the Optional API could be found at the official Java API website

Conclusion

Optional is simply a language feature but it is worth learning the concept and reasoning behind its existence. This is because most languages face the same issue and while individual implementations might have different names, they all operate on similar logic and resolution technique.

Recommended guidelines

  • Optional intended to provide is a limited mechanism for method return types where there is a clear need to represent "no result", and where using null for that is overwhelmingly likely to cause errors.
  • Avoid using Optional.get()
  • Avoid using Optional in fields, method parameters, and collections.

· 8 min read

Motivation

When I completed my first module in NUS, I winced at the thought of applying to be a teaching assistant(TA). I could not understand why one would put himself through reading messy and error-ridden code from students who just started programming. While comments from my TA of that time were helpful, they did not significantly impact my learning.

I changed my impression of TA after my first semester at NUS.

Two things happened

I had a TA who told us "free feel to contact me for any queries and I will respond ASAP". Given that the class size was small(less than 10 students), I made full use of the opportunity to shoot many questions at my TA via the class Discord server. I received responses that were timely and thoughtful. This was great even though I did not require help that often. I had a sense of confidence that no matter what questions that I had in mind, I would have someone who could address them immediately. When I did require help for concepts that were difficult to understand, my TA was able to communicate with me via a Discord voice chat or a screen share. In summary, I had a great "user experience" provided by an excellent teaching staff.

I was also actively involved in a class discussion forum. While I didn't really ask questions, I read through many interesting ones that provoked my thinking. At times I would be drafting an answer to a question raised by another student and I would find loopholes in my justification. Or, when I thought things were supposed to work in a certain way, I would find compilation errors in the example code that I was going to use to illustrate my point. There were many late nights in which I researched and refined my answer to someone's question in the forum. That's when I knew peer learning or learning from what others have to say could be extremely valuable.

I realized that TA could greatly supplement learning and made an impact on how students perceive a module. The second realization is that the students who are taking a module have questions that challenge and poke the module material further. Utilizing that source of learning can make one acquire a deeper understanding of a module, even after taking it. Becoming a TA is a great way to tap on that resource.

My Turn

The application

I am grateful for such TA opportunities available for undergraduate students in NUS. I applied for a TA position in CS2030 Programming Methodology II with the following note to the prof, in case anyone who's interested to see a sample of how I broached the subject:

Hi Prof,

This is Yongliang, a CS student from your module CS2030S. I would like to indicate my interest to be a TA for the next semester.

Coming from background in Python(CS1010X), I was totally not “type aware” and had some difficulties with more complicated languages such as C and Java.

Before the current semester, I took CS2040 with Java and even after that, I had no idea why things were coded in a certain way. For example, why do people

write List<Integer> m = new ArrayList<>(); instead of ArrayList<Integer> m = new ArrayList<>();. So I looked forward to CS2030S very much

before the semester and I would say that this module really make it clear to me three aspects of programming: Java itself, OOP & Functional Programming.

Besides the module content, I also particularly enjoyed meaningful discussions I had with other classmates in our Github issues, where I learned more about type inference

and even things like “target type” and “type witness”. I personally enjoyed this module very much and would love to contribute if possible.

Also taking this opportunity to thank you for your care and support for the students, I appreciate it 😊

The experience

Given that this was my first run as a TA, I would just summarize that the experience was fruitful and humbling. I shall write about it in detail in another blog post.

Reflecting on Teaching Tactics

The whole teaching experience made me realize that teaching is difficult. Like most of the things I do, I then look for ways to improve. I chanced upon the essay "Teaching Tactics" by Eric Hehner near the end of the semester. Eric, who is a computer scientist and a professor at the University of Toronto, wrote about his thoughts and observations on teaching computer science courses. I find the insights expressed by him interesting and would like to discuss those that were surprising to me and gather some actionable items to incorporate into my teaching in the future.

The first point is on "acting stupid". In his essay, Eric described an experiment he conducted. In one of the semesters, he was tasked to teach two sections of the same course. He took on an authoritative attitude with the first class, where he solved all problems and demonstrated his excellent grasp of the material delivered. However, he acted unsure of himself in the second class. He appeared "stupid" and confused when presenting some problems. At the end of the semester, there were two comparisons made by Eric. The first comparison being teaching evaluations. The first class evaluated him to be an excellent professor who knew his stuff. The second class deemed him terrible and incapable to teach the topic. The second comparison being student performance. The first class did not do as well as the second class. While acknowledged by Eric that the standalone experiment would not be able to produce any significant conclusion, I thought it was a creative approach in understanding the best learning environment for students. I felt like I would have acted the same way as students in the two classes.

The second point is on "assignment vs assessment". Briefly speaking, Eric talked about his view that assignments should allow collaborative peer learning and answers should be freely available; Assessments, on the other hand, follow the more traditional examination approach. I thought that the separation is beneficial. As a student, I know that we can't solve all problems and there might be times where we would look for hints online or from our friends. Discussing a particular problem with others would also help us consolidate our learning much better than doing it alone. There is also the issue where we might have given up on attempting a difficult problem after hours of clueless efforts. A nudge from a friend could help tremendously, without revealing the solution itself.

The last point is on "online teaching". Learning has shifted online due to unforeseen circumstances that no one has expected. In his essay, Eric cautioned that simply recording a teacher teaching a class as per offline setting is letting go of the opportunity to harness the prowess of technology. He talked about bite-size videos and making the online sessions interactive by solving problems instead, given that students can view the lecture content beforehand. This got me thinking because I was teaching lab sessions where a problem set will be released and attempted by students in the session. As a TA, I can either do some more sharing of the lecture content that might be useful for students to tackle the problem set, or I can walk around to answer questions when students start to step through the problems. If I spend much time on the former portion, I would unavoidably eat into the time for students to ask me questions during the lab session. This balance is hard to achieve because I realized that explaining the concepts often takes up a lot of time in front of the class.

One possible tweaking, should I be given another chance to TA a programming module, will be that I might look into recording bite-size content to walk through some example code that explains the concepts related. I will then release them before the lab sessions for students to watch. If students are unable to watch it in their own time, they can choose to watch it during the lab session. If they know that they understand certain topics well enough, they can go ahead and attempt questions in the lab and ask me questions if any. This way students have control in deciding what kind of lab setting is most optimum for them. If they find my teaching style and explaining video to be ineffective, they could spare themselves the time and focus on the problem set and the guidance I could provide when they are tackling the questions.

Conclusion

I expect my belief and thinking around the topic of teaching to evolve and therefore will continue to post related content on this area.

Reference: