Skip to content

Commit 1385307

Browse files
authored
1004 wordle (#96)
* chore: subdirectory added with the initial index.md * docs: snippet 1004 added in index.md * fix: snippet corrections
1 parent 2504c7c commit 1385307

2 files changed

Lines changed: 328 additions & 0 deletions

File tree

2.29 KB
Loading

snippets/1004_Wordle/index.md

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
---
2+
layout: default
3+
codename: Wordle
4+
title: Test-Driven Wordle klón fejlesztés MI segítségével
5+
tags: snippets mieset
6+
authors: Várhegyi Melinda
7+
---
8+
9+
# Test-Driven Wordle klón fejlesztés MI segítségével
10+
11+
## A feladat leírása
12+
13+
A feladat egy Wordle szójáték klón elkészítése volt .NET MAUI keretrendszerben, C# nyelven,
14+
Windows platformra célozva (`net8.0-windows10.0.19041.0`), Visual Studio 2022-ben.
15+
A Wordle játék lényege röviden: Egy 5 betűs szavakat tartalmazó szólistából sorsolunk egy feladványt,
16+
melyet a felhasználó megpróbál megfeljebb 6 próbálkozásból kitalálni. Minden beküldött tippjének
17+
betűit kiértéklejük aszerint, hogy a feladvány tartalmazza-e az adott betűt.
18+
(Ugyanazon a helyen tartalmazza - zöld, tartalmazza, de másik helyen - sárga, nem tartalmazza - szürke.)
19+
20+
A fejlesztés során használt MI eszközök:
21+
22+
- **GitHub Copilot Chat (Claude Haiku 4.5)** — a kód generálásához és a TDD ciklus végrehajtásához
23+
- **Claude Sonnet 4.6 (desktop alkalmazás)** — tervezéshez, architektúra döntésekhez, prompt íráshoz és
24+
hibakereséshez
25+
26+
A projekt MVVM architektúrán alapul, a fejlesztés TDD (Test Driven Development)
27+
módszerrel történt, xUnit, Moq és FluentAssertions könyvtárak használatával.
28+
29+
---
30+
31+
## Tanulságok
32+
33+
- **A kontextus átadása kulcsfontosságú.** Minél részletesebb és pontosabb promptot kap a Copilot,
34+
annál jobb kódot generál. Az egyszerű, rövid kérések általában rossz vagy hiányos eredményt adnak.
35+
- **A TDD workflow jól kombinálható az MI-vel**, de egyes tesztek megírása emberi feladat marad —
36+
különösen az összetett edge case-ek esetén (pl. duplikált betűk kezelése a Wordle logikában).
37+
- **Copilot nem látja a renderelt UI-t**, így vizuális hibák debuggolásában (pl. gomb layout)
38+
korlátozott a segítsége. Az ilyen problémákat sajátkezűleg kell megoldani.
39+
- **A Copilot hajlamos hibás architektúra döntéseket javasolni** — pl. rossz target framework,
40+
felesleges `<RuntimeIdentifier>` a `.csproj`-ban, inkompatibilis NuGet csomagok.
41+
Ezeket mindig kritikusan kell értékelni.
42+
- **Az összetett logikai edge case-eket a Copilot nem kezeli helyesen** — a duplikált betűk
43+
Wordle szabály szerinti kiértékelési logikáját kézzel kellett megírni.
44+
- **A kontextus elvész** — ha a Copilot Chat ablak bezárul (pl. VS összeomlás vagy fájlok
45+
áthelyezése után), az összes korábbi kontextus elveszik. Érdemes a kontextus promptot
46+
külön fájlban tárolni és újra beadni.
47+
- **Claude Sonnet 4.6 és Copilot (Claude Haiku 4.5) jól kiegészítik egymást** — Claude
48+
erős volt a tervezésben, architektúrában és hibakeresésben, a Copilot pedig a kód generálásban.
49+
- **A mutációs tesztelés és az MI jól kombinálható** — a Stryker által talált túlélő
50+
mutánsokat Copilottal hatékonyan meg lehet ölni, de a promptot pontosan kell
51+
megfogalmazni: meg kell adni a mutáns pontos helyét és viselkedését.
52+
- **A Copilot törlési feladatoknál megbízhatatlan** — amikor kódot kellett törölni,
53+
Copilot váratlan módosításokat végzett más fájlokban is. Törlési feladatokat
54+
érdemes kézzel elvégezni.
55+
56+
---
57+
58+
## A megvalósított rendszer
59+
60+
### Projektstruktúra (4 projekt)
61+
62+
```
63+
WordleMAUI/ ← .NET MAUI alkalmazás — csak nézetek (XAML)
64+
WordleMAUI.Core/ ← Class Library — modellek és szolgáltatások (pure C#)
65+
WordleMAUI.ViewModels/ ← Class Library — GameViewModel (CommunityToolkit.Mvvm)
66+
WordleMAUI.Tests/ ← xUnit tesztprojekt
67+
```
68+
69+
**Projekt hivatkozások:**
70+
- `WordleMAUI``WordleMAUI.ViewModels``WordleMAUI.Core`
71+
- `WordleMAUI.Tests``WordleMAUI.ViewModels` és `WordleMAUI.Core`
72+
- `WordleMAUI.Tests` nem hivatkozik `WordleMAUI`-ra (WinRT inicializálási hiba miatt)
73+
*Ennek a részleteiről a 3. pontban lesz szó.*
74+
75+
### Főbb komponensek
76+
77+
| Komponens | Leírás |
78+
|---|---|
79+
| `LetterState` | enum: Correct, Misplaced, Absent |
80+
| `GuessResult` | record: char Letter, LetterState State |
81+
| `WordValidator` | 5 betűs, szótárban szereplő szavak ellenőrzése |
82+
| `GuessEvaluator` | Betűnkénti kiértékelés, duplikált betűk helyes kezelésével |
83+
| `GameStateManager` | Játékállapot kezelése (6 kísérlet, nyerés/vesztés) |
84+
| `WordSelector` | Véletlenszerű szókiválasztás |
85+
| `GameViewModel` | MVVM ViewModel, összeköti a logikát és a UI-t |
86+
87+
---
88+
89+
## A munkafolyamat tanulságos részletei
90+
91+
### 1. A TDD workflow MI-vel
92+
93+
A fejlesztés az alábbi ciklust követte minden komponensnél:
94+
95+
```
96+
1. Tesztnevek megírása (szándék leírása)
97+
2. Copilot által tesztek generálása
98+
3. Copilot javaslatának kritikus értékelése
99+
4. Tesztek alapján kód generálása
100+
5. Tesztek futtatása, felmerülő hibák javítása
101+
6. Összes teszt zöld -> kész a komponens
102+
```
103+
104+
Ez a workflow az egyszerűbb komponenseknél (pl. `WordValidator`, `GameStateManager`)
105+
jól működött. Copilot gyorsan generált helyes implementációt, mivel a tesztek neve
106+
egyértelműen leírta a szándékot.
107+
108+
**Példa sikeres promptra (Phase 2 implementáció):**
109+
110+
```
111+
The unit tests for Phase 2 — Core Domain Layer are written and finalized.
112+
Now implement the production code to make all tests pass, one class at a time
113+
in the order below. Do not move to the next class until all tests for the
114+
current one are green.
115+
116+
## Rules
117+
- All strings are uppercase — no case conversion needed in any service
118+
- Use the exact class and interface names specified below
119+
- Do not add any methods or properties that are not required by the tests
120+
- All classes are plain C# with zero UI dependencies
121+
122+
## Implementation Order
123+
[...]
124+
```
125+
126+
### 2. A duplikált betűk problémája
127+
128+
A `GuessEvaluator` implementálása során a duplikált betűk helyes kezelése
129+
nem zajlott zökkenőmentesen. A Wordle szabályai szerint:
130+
131+
- Ha a tippben egy betű többször szerepel, mint a feladványban, a felesleges
132+
előfordulások `Absent` jelölést kapnak
133+
- A helyes pozíciókat (`Correct`) kell először meghatározni, és csak ezután
134+
a rosszul pozicionált (`Misplaced`) betűket
135+
136+
A Copilot még részletes magyarázat után sem generált helyes
137+
duplikált betű logikát. Az ehhez kapcsolódó teszteket végül kézzel kellett megírni.
138+
139+
**Példa edge case teszt (kézzel írva):**
140+
141+
```csharp
142+
[Fact]
143+
public void GivenDuplicateLetterInGuess_WhenOnlyOneExistsInSecret_ShouldMarkSecondAsAbsent()
144+
{
145+
var guess = "AWAKE"; // Two A's in guess
146+
var secret = "STARE"; // Only one A in secret at position 2
147+
148+
var result = _evaluator.Evaluate(guess, secret);
149+
150+
result.Should().HaveCount(5);
151+
// A is in STARE at position 2, BUT the other A in guess at position 2 is correct -> Absent
152+
result[0].State.Should().Be(LetterState.Absent);
153+
// W is not in STARE -> Absent
154+
result[1].State.Should().Be(LetterState.Absent);
155+
// A is in STARE at position 2 (correct position in guess) -> Correct
156+
result[2].State.Should().Be(LetterState.Correct);
157+
// K is not in STARE -> Absent
158+
result[3].State.Should().Be(LetterState.Absent);
159+
// E is in STARE at position 4 (correct position in guess) -> Correct
160+
result[4].State.Should().Be(LetterState.Correct);
161+
}
162+
```
163+
164+
**Tanulság:** Az összetett üzleti logikát tartalmazó teszteket nem érdemes
165+
a Copilotra bízni. Az ilyen tesztek megírása emberi feladat, a Copilot feladata az
166+
implementáció generálása a tesztek alapján.
167+
168+
### 3. Architektúra probléma — WinRT hiba a tesztek futtatásakor
169+
170+
Az első megközelítésben a tesztprojekt közvetlenül hivatkozott a MAUI projektre.
171+
Ez `System.TypeInitializationException` hibát okozott, mert a MAUI projekt
172+
betölti a WinRT runtime-ot, ami nem elérhető a tesztfuttató környezetben.
173+
174+
**Copilot javasolta megoldás:** A tesztprojekt target frameworkjét `net8.0`-ra
175+
állítani — ez hibás volt, mert a framework eltérése miatt a projekthivatkozás
176+
sem működött.
177+
178+
**Helyes megoldás:** Külön osztálykönyvtár projektek
179+
létrehozása (`WordleMAUI.Core` és `WordleMAUI.ViewModels`), amelyek nem
180+
húzzák be a WinRT függőségeket. A tesztprojekt csak ezekre hivatkozik,
181+
a MAUI projektre nem.
182+
183+
**Tanulság:** A Copilot hajlamos a legegyszerűbb technikai megoldást javasolni,
184+
ami nem mindig az architektúrailag helyes döntés. Az ilyen döntéseknél emberi
185+
felülvizsgálat szükséges.
186+
187+
### 4. Projekt konfiguráció hibák — .csproj problémák
188+
189+
Copilot több hibás `.csproj` módosítást javasolt:
190+
191+
| Copilot javaslata | Probléma | Helyes megoldás |
192+
|---|---|---|
193+
| `<TargetFramework>net8.0</TargetFramework>` a tesztprojektben | Framework eltérés, hivatkozás nem működik | `net8.0-windows10.0.19041.0` |
194+
| `<RuntimeIdentifier>win10-x64</RuntimeIdentifier>` | Felesleges, projekt hivatkozási problémákat okoz | Törlés |
195+
| `CommunityToolkit.Maui` NuGet csomag | Verzió inkompatibilitás | Csomag eltávolítása |
196+
197+
**Tanulság:** A `.csproj` fájlokat mindig kritikusan kell átnézni, mielőtt
198+
elfogadjuk a Copilot javaslatát. Ha valami furcsának tűnik, valószínűleg az is.
199+
200+
### 5. A kontextus prompt fontossága
201+
202+
Mivel a Copilot Chat nem őrzi meg a kontextust munkamenetek között (pl. VS
203+
összeomlás, fájlok áthelyezése után), részletes kontextus promptot kellett készíteni,
204+
amelyet minden új munkamenet elején be kellett adni. Ez tartalmazta:
205+
206+
- A projekt teljes struktúráját
207+
- Az összes projekt hivatkozást
208+
- A már implementált komponensek interfészeit
209+
- A fejlesztési konvenciókat (csak nagybetűs szavak, nincs `CommunityToolkit.Maui` stb.)
210+
- Az aktuális fázist és feladatot
211+
212+
**Példa kontextus prompt részlet:**
213+
214+
```
215+
You are helping me build a Wordle clone called WordleMAUI using .NET MAUI
216+
targeting net8.0-windows10.0.19041.0 in Visual Studio 2022 with .NET 8.0.
217+
[...]
218+
Note: CommunityToolkit.Maui is NOT installed due to version incompatibility.
219+
Do not suggest or use any APIs from it.
220+
[...]
221+
We follow strict TDD: tests are always written before implementation.
222+
Never generate implementation before tests unless I ask.
223+
```
224+
225+
**Tanulság:** Minél pontosabb és részletesebb a kontextus prompt, annál kevesebb
226+
hibás javaslatot ad a Copilot. A negatív megszorítások (pl. "ne használd ezt a
227+
csomagot") különösen fontosak.
228+
229+
### 6. A UI fejlesztés kihívásai
230+
231+
A MAUI XAML UI generálásánál a Copilot hasznos volt az alapstruktúra elkészítésében,
232+
de a vizuális hibák javításában korlátozott segítséget nyújtott, mivel nem látja
233+
a renderelt eredményt.
234+
235+
**Konkrét példa — billentyűzet layout:**
236+
A virtuális billentyűzet gombjainak helyes elhelyezése több lépésen keresztül tartott:
237+
- Copilot egymás után javasolt fix pixel szélességeket, padding és margin értékeket
238+
- Ezek egyike sem oldotta meg a problémát
239+
- A végső megoldás a MAUI `Button` vezérlő `MinimumWidthRequest="0"` tulajdonsága
240+
volt
241+
242+
**Tanulság:** A vizuális UI debuggolás emberi feladat. A Copilot tud XAML kódot
243+
generálni, de a renderelt eredményt nem látja, ezért vizuális javításra
244+
nem feltétlenül alkalmas.
245+
246+
247+
### 7. Mutációs tesztelés Stryker.NET-tel
248+
249+
A fejlesztés végén mutációs tesztelést végeztünk a Stryker.NET eszközzel (v4.14.0)
250+
a `WordleMAUI.Core` projekt tesztelési minőségének mérésére.
251+
252+
**A mutációs tesztelés folyamata:**
253+
A Stryker apró változtatásokat ("mutációkat") végez a forráskódon, majd lefuttatja
254+
a teszteket. Ha egy mutáció nem buktatja el a teszteket, az azt jelenti, hogy
255+
a tesztek nem fedik le megfelelően azt a logikát — ez egy túlélő mutáns.
256+
257+
**A tesztelés eredményei:**
258+
259+
- **Első futtatás: 74.00%**
260+
- **`SelectByDate` eltávolítása után: 80.43%**
261+
A `SelectByDate` egy olyan teszt volt, amely a TDD fejlesztés során megírásra került,
262+
viszont később ez a funkció mégsem került implementálásra a fejlesztő döntése miatt.
263+
Így ennek a tesztnek az eltávolítása rögtön növelte a mutáció score-t.
264+
- **`GameStateManager` tesztek után: 89.13%**
265+
A hibák abból eredtek, hogy nem volt lekezelve az, ha az egyes függvéynek
266+
bemeneti paraméterül null-t kapnak.
267+
- **`WordSelector` tesztek után: 93.48%**
268+
A `wordList` konstruktorában null argumentum kezelése.
269+
- **`WordValidator` + `GuessEvaluator` tesztek után: 100.00%**
270+
`WordValidator` - null kezelése. `GuessEvaluator` - Ha egy betűt már megjelöltünk
271+
Correct-ként, akkor az ő helye `processed[i] = true` jelölést kap. A mutáns ezt false-ra
272+
állította, ekkor a betű a következő iterációban újra kiértékelésre került Misplaced
273+
vagy Absent-ként, ami hibás, ezt kellett lekezelni.
274+
275+
**A Stryker konfigurálásának nehézségei:**
276+
A Stryker beüzemelése számos kihívással járt, amelyek mind a `.csproj` konfiguráció
277+
sajátosságaiból eredtek:
278+
- A `stryker-config.json` helyes formátumát Copilot rosszul generálta
279+
- A `console` reporter neve Stryker 4.14.0-ban `cleartext` — ezt is tévesen adta meg
280+
- A `mutate` path filter nem működött relatív útvonalakkal, csak `**/*.cs` mintával
281+
- A `LinqMutator` érvénytelen kódot generált `List<string>.Count` mutációjakor,
282+
amit az `ignore-mutations: ["linq"]` beállítással kellett kizárni
283+
284+
**A Stryker + Copilot workflow:**
285+
A leghasznosabb megközelítésnek az bizonyult, amikor a Stryker riportból azonosított túlélő
286+
mutánsokat Copilottal öltük meg. A workflow:
287+
288+
```
289+
1. Stryker futtatása → HTML riport generálása
290+
2. Túlélő mutáns azonosítása a riportban (fájl + sor + mutáció típusa)
291+
3. Copilot Chat: pontos prompt a mutáns megöléséhez szükséges teszttel
292+
4. Teszt hozzáadása → Stryker újrafuttatása → score javulás ellenőrzése
293+
```
294+
295+
**Tanulság:** A mutációs tesztelés hasznos eszköz a tesztek minőségének mérésére,
296+
de a konfigurálása összetett és eszközismeretet igényel. A Copilot segíthet
297+
a tesztek generálásában, de a mutáns azonosítása és a prompt pontos
298+
megfogalmazása emberi feladat marad.
299+
300+
**Megjegyzés:**
301+
A 100%-os mutáció score azt jelenti, hogy minden meglevő kódsor tesztelve
302+
van — de nem jelenti azt, hogy a szoftver helyes. A Stryker csak a meglévő
303+
kódot tudja mutálni, hiányzó funkciókat vagy hibás üzleti logikát nem képes
304+
detektálni. Jó példa erre a duplikált betűk kezelése: ha a `GuessEvaluator`
305+
eleve rossz algoritmust tartalmazott volna, a Stryker azt nem találta volna
306+
meg — csak a kézzel megírt, üzleti logikán alapuló tesztek tudták garantálni
307+
a helyes viselkedést.
308+
309+
---
310+
311+
## Összefoglalás
312+
313+
A TDD és az MI eszközök kombinációja hatékony fejlesztési módszernek bizonyult,
314+
de fontos tanulság, hogy az MI nem helyettesíti a fejlesztői tudást — inkább
315+
egy erős asszisztens, amely felgyorsítja a munkát, de folyamatos emberi
316+
felügyeletet igényel.
317+
318+
A legjobb eredményt akkor értük el, amikor:
319+
1. A fejlesztő írta meg a tesztek leírását
320+
(NEM az MI dönti el, hogy milyen tesztesetekre lesz szükségünk)
321+
2. A teszteket vagy MI generálta és alaposan ellenőrizte őket a fejlesztő,
322+
vagy maga a fejlesztő írta
323+
3. A Copilot legenerálta az implementációt a tesztek alapján
324+
4. A fejlesztő itt is kritikusan értékelte és szükség esetén javította a javaslatot
325+
5. Claude segített az összetettebb promptok megírásában és a nehezebb hibák azonosításában
326+
327+
**Szerző:** Várhegyi Melinda
328+

0 commit comments

Comments
 (0)