Your blog entry must explicitly answer the following questions about the class (mark the questions in bold in your post):
I was the first to submit my merge request for project #2 (voting).
I recognized that checktestdata
is not capable of
generating only valid voting test cases, so I wrote my own generator in
my favorite programming language (Swift).
I posted my Voting.ctd.txt
file to Ed and I’m pretty
sure other people used it.
The biggest problem with this paper and idea is the way Martin presents it in an object-oriented context. I think it works better in a functional setting.
Martin mentions a bowling game from a prior chapter in the book and
talks about having separate Game
and Scorer
objects. Java forces us to put all code into methods, so if you want to
separate the scoring algorithm from the game state (a questionable
decision), you’re forced to create a Scorer
class. But in
other programming languages (including C++), you can write a free
function to implement the scoring algorithm, which seems like a better
idea to me.
The ability to declare a value as const
is useful, but
C++ doesn’t go far enough. When you pass me a
vector<int> const &v
, I can’t modify the size of
v
or any of its elements, which is a useful guarantee for
me to make to you. But you haven’t guaranteed to me that v
will remain unchanged. For example, if I want to save v
in
an instance property, I have to defensively copy it if I want to be sure
it will not be changed while I’m “not looking”. There is no
compiler-enforced way for you to promise me that v
will not
change.
Native arrays are a bug-prone blemish inherited from C. We should stick to bounds-checked containers wherever possible.
Algorithms are great, but C++’s implementations are opaque and
inconvenient. Prior to the “Concepts” feature added in C++20, there was
no way to express to the compiler that your algorithm requires (for
example) a bidirectional iterator; you’d just call the function and hope
(but probably fail) to understand the error message if the values you
passed in were lacking some critical method or operator. Furthermore, in
the name of efficiency, the C++ standard library lacks many convenient
methods we may know and love from other languages: compare the pain of
using C++’s
std::transform
function to the joy and ease of using
the map
function in Javascript
or Ruby
or Perl or Swift
or Elm
or Haskell
or Rust
or Scala
or Kotlin
or C#
or you get the idea.
Iterators are the perfect example of why C++ so badly needed the “concepts” and “constraints” that were finally added in C++20.
I enjoyed helping my nephew with his calculus homework. I’m nerdy that way.
My tip this week comes from Edsger Dijkstra, Turing Award winner and former professor of computer science at UT:
Program testing can be used to show the presence of bugs, but never to show their absence!
See you next week!