Code Kata: staňte sa lepším programátorom
Ako sa stať lepším programátorom? Pomáha poznať teóriu ale dôležitá je najmä prax. Podobne ako môžu trénovať hudobníci alebo športovci môžeme trénovať aj my programátori, napríklad pomocou tzv. Code Katas.
Kata je cvičenie v karate, ktoré sa opakuje stále dookola a každým opakovaním sa vaše schopnosti mierne zlepšujú. Princíp Code Katas je podobný, každá Code Kata je krátke 30-60 minútové cvičenie. Niektoré cvičenia zahrňujú programovanie a môžu byť vyriešené rôznymi spôsobmi, niektoré vyžadujú rozmýšľanie o problémom spojených s programovaním.
Code Katas existuje veľké množstvo pre rôzne programovacie jazyky (viď napríklad tento zoznam alebo tento web), vo všeobecnosti však nezáleží, v akom jazyku dané cvičenie riešite.
String Calculator
Keďže sa v súčasnosti zaujímam o F#, vybral som si Code Kata nazvanú String Calculator a rozhodol som sa ju vyriešiť v F# aj C#. Zadanie nasledovné:
- Create a simple String calculator with a method int Add(string numbers)
- The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0) for example “” or “1” or “1,2”
- Start with the simplest test case of an empty string and move to 1 and two numbers
- Remember to solve things as simply as possible so that you force yourself to write tests you did not think about
- Remember to refactor after each passing test
- Allow the Add method to handle an unknown amount of numbers
- Allow the Add method to handle new lines between numbers (instead of commas).
- the following input is ok: “1\n2,3” (will equal 6)
- the following input is NOT ok: “1,\n” (not need to prove it - just clarifying)
-
- to change a delimiter, the beginning of the string will contain a separate line that looks like this: “//[delimiter]\n[numbers…]” for example “//;\n1;2” should return three where the default delimiter is ‘;’ .
- the first line is optional. all existing scenarios should still be supported
- Calling Add with a negative number will throw an exception “negatives not allowed” - and the negative that was passed.if there are multiple negatives, show all of them in the exception message
Celé cvičenie by vám nemalo zabrať viac ako 30 minút. Úloha je to celkom jednoduchá, vymyslieť elegantné riešenie však nie je tak jednoduché, ako sa na prvý pohľad môže zdať.
Moje riešenie
F#
open System
let MakeList (s:string)=
if (s.StartsWith "//" ) then
let (parts:string array) = Array.ofSeq(s.Split([|'\n'|],2))
let delims = [|parts.[0].Replace("//","")|]
List.ofSeq(parts.[1].Split(delims, StringSplitOptions.None))
else
List.ofSeq(s.Split [|',';'\n'|])
let Add (s:string)=
if (String.IsNullOrEmpty(s)) then 0
else
let numbers = List.map (fun n->int n) (MakeList s)
let negatives = List.filter (fun n -> n < 0) numbers
if (negatives.Length>0) then
failwith ("negatives not allowed "+ (List.reduce (fun acc elem -> acc+","+elem) (List.map (fun n->n.ToString()) negatives)))
else
List.reduce (fun acc elem -> acc + elem) numbers
C#
public IEnumerable MakeList(string s)
{
if (s.StartsWith("//"))
{
var parts = s.Split(new string[]{"\n"},StringSplitOptions.None);
var delims = new string[]{parts[0].Replace("//","")};
return parts[1].Split(delims,StringSplitOptions.None).Select(l=>Int32.Parse(l));
}
return s.Split(new char[]{',','\n'}).Select(l=>Int32.Parse(l));
}
public int Add(string s)
{
if (String.IsNullOrEmpty(s)) return 0;
var numbers = MakeList(s);
var negatives = numbers.Where(l=> l < 0);
if (negatives.Any())
{
throw new ArgumentException("Negatives not allowed "+String.Join(",",negatives.Select(l=>l.ToString()).ToArray()));
}
return numbers.Aggregate(0, (acc,elem) => acc+elem);
}
Máte riešenie v C#, F# alebo akomkoľvek inom jazyku? Podeľte sa o neho. Zdrojové kódy by boli v komentátoroch ťažko čitateľné, založil som preto pre tento článok vlákno na webe Smartmánie.
Zaujímavé Code Katas
Code Kata
Coding Kata .NET
TDD Kata 1
Project Euler