My first D module - Critiques welcome.
bearophile
bearophileHUGS at lycos.com
Mon Dec 23 14:38:57 PST 2013
John Carter:
> I also attempted to do it in "Best Practice Test Driven
> Development" form
I think it's important to write lot of unittests (and use other
kind of tests, automatic testing like in Haskell, fuzzy testing,
integration tests, smoke tests, etc), but I think Test Driven
Development is mostly silly. It's better to actually think a good
solution before writing your code. Thinking-Driven Development is
better.
> I would welcome any critique, advice, flames, recommendations,
> etc. etc.
This is a first pass, I have not studied the logic of your code
nor other higher level things.
The importance of my comments is not uniform, some of them are
important, while others are more based on my taste.
> import core.exception;
> import std.array;
> import std.algorithm;
> import std.stdio;
> import std.utf;
> import std.range;
I usually prefer to put the more general modules first. So stdio
goes first.
> /++ Convert an unsigned integer to a roman numeral string. +/
For single-line ddoc comments the /// is enough.
For the other situations /** */ is enough.
/++/ is probably better left to comment out code.
> pure string toRoman( in uint i)
I suggest to never put a space after the opening (.
> /++ Convert an unsigned integer to a roman numeral string. +/
> pure string toRoman( in uint i)
This is a very simple to use function, but in general don't
forget to list every argument and return in the function ddoc
using the specific ddoc syntax.
> assert( i != 0);
Sometimes you can also add a comment in the assert that explains
why this precondition has failed.
> return romanSystem[$-1].toRomansWithZero( i);
[$-1] is OK. But sometimes also the usage of ".back" is OK.
> return fromRomanDigitArray( romanToDigitArray( roman));
More readable and less noisy:
> return roman.romanToDigitArray.fromRomanDigitArray;
Also, the "array" suffix to those names is probably too much
tying to the implementation, so better to remove the "array".
> struct romanSystemData {
In D struct/class/union names start with an uppercase.
> dchar digit; /// UTF32 representation of each roman
> digit
> uint value; /// Integer value of digit
The alignment is nice, but it burns a little of coding time (if
it's the IDE to do it then I guess it's OK).
> pure string toRomansWithZero( in uint i) const
Annotations like "pure" are in my opinion better on the right,
after const.
> return toUTF8([digit]) ~ toRomansWithZero( i - value);
More missing UCSF.
> if( 0 == previous) {
This Yoda Style is not needed in D, because D doesn't compile
code like "if (previous = 0)".
> return "";
Alternative is "return null;".
> immutable auto delta =
> (value-romanSystem[regionIndex].value);
auto is not needed here. And usually put a space before and after
every operator, for readability:
immutable delta = (value -
romanSystem[regionIndex].value);
> return toUTF8( [romanSystem[regionIndex].digit,
> digit]) ~ romanSystem[regionIndex].toRomansWithZero( i -
> delta);
I have not studied the logic of this code, but are you sure
toUFT8 is needed to convert Arabic numbers to Roman and the other
way around?
> // Test the 'I''s
> unittest {
Some unittest system allows to put that comment "Test the 'I''s"
in a more active role. So it's shown on screen when the relative
unittest fails.
Also, I suggest to add some "ddoc unittests". It's a feature
recently added to D.
> // The romans were crazy M
> unittest {
> assert( "CMXCIX" == toRoman( 999));
> }
Most of your unittests are in-out pairs. So you can shorten them
with a in-out table.
> return array(map!((a) => romanToDigit(a))(roman));
That's quite bad code. Better:
return roman.map!romanToDigit.array;
> if( 0 == digitArray.length) {
==>
if (digitArray.empty) {
> auto smallerStuff = smallerThanLast( digitArray);
> auto smallerStuffValue = fromRomanDigitArray( smallerStuff);
> auto biggerStuff = digitArray[
> 0..($-smallerStuff.length-1)];
> auto biggerStuffValue = fromRomanDigitArray( biggerStuff);
Perhaps you want some const annotations.
> foreach( i; 1..2014) {
==>
foreach (immutable i; 1 .. 2014) {
Bye,
bearophile
More information about the Digitalmars-d-learn
mailing list