Extra opdracht OOP - Doortje Geuze¶
Voor dit blok heb ik een extra opdracht gekregen om te werken aan object oriented programming, oftewel: OOP.
OOP gaat in het kort over het maken van objecten die zowel gegevens als methods bevatten. OOP creëert voor meer structuur in de code wat de code herbruikbaarder maakt, dit zorgt ervoor dat er tijd bespaart kan worden met het coderen.(w3schools.com)
In OOP bestaan er vier pilaren, deze zijn: abstraction, encapsulation, inheritance en polymorphism. In deze opdracht ga ik deze pilaren uitleggen en ondersteunen met code uit mijn eigen projecten.
Abstraction¶
Bij abstraction gaat het over het verstoppen van informatie en de code makkelijker te maken door minder belangrijke details weg te laten, hierdoor kan je focussen op de belangrijke code en wordt de code makkelijker leesbaar. (C. Gupta, Datatrained.com)
Er zijn verschillende methods om informatie te verstoppen in programmeren
Abstract classes¶
Abstract classen in CSharp¶
In programmeertalen zoals C# en java heb je de abstract
keyword voor abstract classes.(learn.microsoft.com) Dit houdt in dat je met het keyword aangeeft dat de class alleen bedoeld is als basis-class van andere klassen en niet op zichzelf wordt geïnstantieerd
Een voorbeeld hoe je dat kan aangeven in C# is door abstract
te zetten voor de class zoals aangegeven hieronder:
Piece
class is nu abstract en wordt dus als basis-class beschouwd. Nu kunnen classen van de piece
class inheriten om alle methods en properties te krijgen en wel geïnstantieerd worden.
Abstract classes in Javascript¶
Een voorbeeld van een abstract class in JavaScript is de TileGrid
class in het project van blok 2. Deze abstract class is abstract, want de class is niet gemaakt om instanties van te maken. Het is een abstract concept waar op basis van classes gemaakt van kunnen worden. Je zou het dus kunnen beschouwen als een soort ‘blueprint’ om anderen classes op te bouwen.
De TileGrid class is een class waar dit gebeurt. De class heeft properties en methods alleen is deze gemaakt als een blueprint voor de Normal- en SpecialTileGrid class. Deze classes hebben beide de functionaliteit van de TileGrid class, maar ze hebben ook anderen functies die de ander niet hoeft.
class TileGrid {
//static #instance; // currently incomplete singleton, should be abstract
#tileSize; // "protected"
#tiles; // "protected"
#width; // "protected"
#height; // "protected"
constructor(width, height, tileSize) {
this.#tileSize = tileSize;
this.#width = width;
this.#height = height;
}
getTileFromGridPosition(gridPosition) {
if (gridPosition.x < 0 || gridPosition.x >= this.#width || gridPosition.y < 0 || gridPosition.y >= this.#height) {
return null;
}
let tile = this.#tiles[gridPosition.x][gridPosition.y];
return tile;
}
getGridPosition(position) {
const gridXPosition = Math.floor(position.x / this.#tileSize);
const gridYPosition = Math.floor(position.y / this.#tileSize);
const gridPosition = createVector(gridXPosition, gridYPosition);
return gridPosition;
}
getTileFromPosition(position) {
return this.getTileFromGridPosition(this.getGridPosition(position));
}
get _width() {
return this.#width;
}
get _height() {
return this.#height;
}
get _tileSize() {
return this.#tileSize;
}
get _tiles() {
return this.#tiles;
}
set _tiles(value) {
this.#tiles = value;
}
}
class NormalTileGrid extends TileGrid {
#tileTypeArray;
#scoreMap;
#nTypes;
#numberOfMatches;
#matching;
#gravity;
#comboMultiplier;
constructor(width, height, tileSize, manager) {
super(width, height, tileSize);
this.manager = manager;
this.#tileTypeArray = [
"taco",
"ruffle",
"babloon",
"dabloon",
"pringle"
];
this.#scoreMap = {
3: 10000,
4: 20000,
5: 50000,
"combo!": 50000
};
this.#nTypes = this.#tileTypeArray.length;
this.#numberOfMatches = 0;
this.#matching = true; // for spawning tiles this needs to be true
this.#gravity = false;
this.#comboMultiplier = 0;
this.#generateTileGrid();
}
draw() {
for (let x = 0; x < this._width; x++) {
for (let y = 0; y < this._height; y++) {
if (this._tiles[x][y] !== null) {
this._tiles[x][y].draw();
}
// this._tiles[x][y].animate();
}
}
if (this.#matching === true) {
// this.getAndResolve();
}
else if (this.#gravity === true) {
this.moveFloatingTilesDown();
}
else {
// this.spawnNewTiles();
}
// draws inputHandler.selectedTile over all tiles so it takes priority
if (inputHandler.selectedTile !== null) {
inputHandler.selectedTile.draw();
}
}
#generateTileGrid() {
//tiles is a 2D array, meaning that it is an array of arrays.
//see https://www.freecodecamp.org/news/javascript-2d-arrays/ for more information about 2D arrays.
this._tiles = new Array();
//generate tile grid here and place tiles in the 2D #tile array.
for (let x = 0; x < this._width; x++) {
this._tiles[x] = new Array();
for (let y = 0; y < this._height; y++) {
do {
this._tiles[x][y] = new NormalTile(
this.#getRandomTileType(),
this._tileSize,
x,
y,
this
);
// } while (true === false);
} while (this.#findMatch3(x, y) === true);
// } while (this.#findAndResolveMatches() !== false)
}
}
this.#numberOfMatches = 0;
this.#matching = false;
this.#gravity = false;
}
#getRandomTileType() {
return this.#tileTypeArray[Math.round(random(0, this.#nTypes - 1))];
}
swapTiles(tile1, tile2) {
if (moving === false) {
// moving = true;
if (tile1 !== null &&
tile2 !== null &&
// this.#findAllMoving() === false &&
tile1 !== tile2) {
const gridPosition1 = this.getGridPosition(tile1.position);
const gridPosition2 = this.getGridPosition(tile2.position);
this._tiles[gridPosition2.x][gridPosition2.y] = tile1;
this._tiles[gridPosition1.x][gridPosition1.y] = tile2;
// if (tile1 !== null && tile2 !== null) {
if (this.getAllMatches().length > 0) {
if (betaAnimationMode === true) {
tile1.animateToOne(gridPosition2.mult(tile1.size));
tile2.animateToTwo(gridPosition1.mult(tile2.size));
// this.getAndResolve();
// setTimeout(() => {
// this.spawnNewTiles();
// }, 2000);
}
else {
tile1.moveTo(gridPosition2.mult(tile1.size));
tile2.moveTo(gridPosition1.mult(tile2.size));
this.getAndResolve();
this.moveFloatingTilesDown();
setTimeout(() => {
moving = false;
this.spawnNewTiles()
}, 1000);
}
console.log("Match!")
}
else {
console.log("Nah, no match.")
this._tiles[gridPosition2.x][gridPosition2.y] = tile2;
this._tiles[gridPosition1.x][gridPosition1.y] = tile1;
}
}
else {
return;
}
}
}
#handleMove() {
this.manager.moves.update(1);
if (this.manager.moves.left < 1 && this.manager.score.currentScore < this.manager.score.goalScore) {
alert("you lost ):");
whichScreen = "select screen";
}
else {
console.log(this.manager.moves.left);
}
}
swapGravityTiles(tile1, tile2) {
if (tile1.normalMoving === false && tile2.normalMoving === false) {
const gridPosition1 = this.getGridPosition(tile1.position);
const gridPosition2 = this.getGridPosition(tile2.position);
this._tiles[gridPosition2.x][gridPosition2.y] = tile1;
this._tiles[gridPosition1.x][gridPosition1.y] = tile2;
else {
return;
}
}
#findMatch3(x, y) {
// if right two tiles are regular tiles
// if left two tiles are same type as tile
if (this.#matching === true) {
console.log(this.#matching);
if (x > 1 &&
this._tiles[x][y] !== null &&
this._tiles[x - 1][y] !== null &&
this._tiles[x - 2][y] !== null &&
this._tiles[x][y].normalMoving === false &&
this._tiles[x - 1][y].normalMoving === false &&
this._tiles[x - 2][y].normalMoving === false &&
this._tiles[x - 1][y].type === this._tiles[x][y].type &&
this._tiles[x - 2][y].type === this._tiles[x][y].type
) {
console.log("match!");
}
// if upper two tiles are regular tiles
// if upper two tiles are the same type as tile
if (y > 1 &&
this._tiles[x][y] !== null &&
this._tiles[x][y - 1] !== null &&
this._tiles[x][y - 2] !== null &&
this._tiles[x][y].normalMoving === false &&
this._tiles[x][y - 1].normalMoving === false &&
this._tiles[x][y - 2].normalMoving === false &&
this._tiles[x][y - 1].type === this._tiles[x][y].type &&
this._tiles[x][y - 2].type === this._tiles[x][y].type
) {
return true
}
}
#findAllMatch3() {
for (let x = 0; x < this._width; x++) {
for (let y = 0; y < this._height; y++) {
this.#findMatch3(x, y);
}
}
}
// line solver
getMatchPerLine(lineArray) {
let matchArray = [];
let nMatches = 1;
// for array length (width/height) - 1 (since it shouldn't have to check on the last tile)
for (let i = 0; i < lineArray.length - 1; i++) {
// if tile type is same as next tile type in array
if (lineArray[i].type === lineArray[i + 1].type) {
console.log(`type ${i}: ${lineArray[i].type}`);
console.log(`type ${i + 1}: ${lineArray[i + 1].type}`);
console.log("they match!");
nMatches += 1;
if (nMatches > 2) {
console.log("Match > 2!");
// for number of matches
for (let j = 0; j < nMatches; j++) {
console.log(`i - j = ${i - j}`);
// if matches array excludes tile that wants to be added
// (this is in case of match 4 or 5)
if (matchArray.includes(lineArray[i - j + 1]) === true) {
// do nothing
}
else {
// add every tile that matches
matchArray.push(lineArray[i - j + 1]);
}
}
}
}
else {
console.log(`type ${i}: ${lineArray[i].type}`);
console.log(`type ${i + 1}: ${lineArray[i + 1].type}`);
console.log("They do not match!");
console.log(`last matches streak: ${nMatches}`);
nMatches = 1;
}
}
return matchArray;
}
// all lines match getter
getAllMatches() {
// get all vertical matches
let allMatchesArray = [];
for (let y = 0; y < this._height; y++) {
console.log(`checking vertical line array ${y}...`);
let verticalLineArray = this.tiles[y];
let matchesFromArray = this.getMatchPerLine(verticalLineArray);
console.log(`received horizontal array`);
allMatchesArray = allMatchesArray.concat(matchesFromArray);
}
// get all horizontal matches
for (let x = 0; x < this._width; x++) {
// create horizontal array from 2d array
let horizontalLineArray = [];
for (let x2 = 0; x2 < this._width; x2++) {
horizontalLineArray.push(this.tiles[x2][x]);
}
let matchesFromArray = this.getMatchPerLine(horizontalLineArray);
console.log(`received horizontal array`);
allMatchesArray = allMatchesArray.concat(matchesFromArray);
}
return allMatchesArray;
}
// collects matched cats and replaces the cat position with null
collectMatches(allMatchesArray) {
allMatchesArray.forEach((tile) => {
console.log(tile.x);
if (this.tiles[tile.x][tile.y] !== null) {
this.tiles[tile.x][tile.y].collect();
}
});
}
// gets all matches and resolved them
getAndResolve() {
console.log("matching")
this.collectMatches(this.getAllMatches());
}
moveFloatingTilesDown() {
console.log("gravitating");
// reversed for loop
let upperTileObjectArray = [];
// let upperTileCounter = 0;
for (
let y = this._height - 1, y2 = 0;
y >= 0;
y--, y2++
) {
for (let x = 0; x < this._width; x++) {
if (this.tiles[x][y].visible === false) {
let voidTile = {
name: "void tile",
description: "proxy object for tile which is null",
x: x,
y: y
};
console.log(`void tile found @(${x}, ${y})`);
for (let i = 0; i < y + 1; i++) {
console.log(`producing upper tile @ (${x},${y - i})`);
let upperTile = this.tiles[x][y - i];
if (upperTile.visible === true) {
console.log(`upper tile found @(${upperTile.x}, ${upperTile.y})`);
let upperTileObject = {
tile: upperTile,
x: upperTile.x,
y: upperTile.y,
xDistanceBetweenVoid: x - upperTile.x,
yDistanceBetweenVoid: y - upperTile.y,
yIteration: i
};
if (upperTileObject.tile.visble === true) {
console.log("upper tile should exist");
console.log(upperTileObject.tile);
}
else {
console.log("upper tile somehow doesn't exist");
}
upperTileObjectArray.push(upperTileObject);
console.log("added to upperTileObjectArray");
console.log(upperTileObjectArray);
// end for loop
i = y + 1;
}
}
}
}
let gravityMap = new Map();
console.log(upperTileObjectArray);
upperTileObjectArray.forEach(obj => {
let upperGridPosition = createVector(
obj.x,
obj.y
);
console.log(`upper grid position: ${upperGridPosition}`)
console.log(`upper tile:`)
console.log(obj.tile);
console.log(`upper grid position: @(${upperGridPosition.x},${upperGridPosition.y})`);
for (let i = 0; i < upperGridPosition.y + 1; i++) {
console.log(i);
console.log(upperGridPosition.y - i);
let upperUpperGridPosition = createVector(
upperGridPosition.x,
upperGridPosition.y - i
);
console.log(`upper upper grid position @(${upperGridPosition.x},${upperUpperGridPosition.y})`);
console.log(`uut x: ${this.tiles[upperUpperGridPosition.x]}`);
console.log(`uut:`);
console.log(this.tiles[upperUpperGridPosition.x][upperUpperGridPosition.y]);
let upperUpperTile = this.tiles[upperUpperGridPosition.x][upperUpperGridPosition.y];
let newUpperUpperGridPosition = createVector(
upperUpperGridPosition.x,
upperUpperGridPosition.y + obj.yDistanceBetweenVoid
);
gravityMap.set(upperUpperTile, newUpperUpperGridPosition);
}
});
gravityMap.forEach((newUpperUpperGridPosition, upperUpperTile) => {
console.log(`tile: ${upperUpperTile}, endPosition: ${newUpperUpperGridPosition}`);
let newUpperUpperEndPosition = createVector(
newUpperUpperGridPosition.x * this.tileSize,
newUpperUpperGridPosition.y * this.tileSize
);
let newVoidTile = this.getTileFromGridPosition(
newUpperUpperGridPosition,
newUpperUpperGridPosition
);
this.swapGravityTiles(upperUpperTile, newVoidTile);
upperUpperTile.animateGravity(newUpperUpperEndPosition);
});
}
this.#gravity = false;
// this.spawnNewTiles();
}
spawnNewTiles() {
// if (this.#gravity === false) {
while (this.#findAllMoving() === true) {
return;
}
console.log("spawning new tiles");
for (let x = 0; x < this._width; x++) {
for (let y = 0; y < this._height; y++) {
if (this._tiles[x][y].visible === false || this._tiles[x][y] === null) {
this.#numberOfMatches += 1;
this._tiles[x][y] = new NormalTile(
this.#getRandomTileType(),
this._tileSize,
x,
y,
this
);
}
}
}
if (this.getAllMatches.length > 0) {
this.#handleScore();
this.#handleMove();
this.getAndResolve();
this.moveFloatingTilesDown();
this.spawnNewTiles();
return;
}
else {
this.#handleScore();
this.#handleMove();
return;
}
}
#handleScore() {
switch (this.#numberOfMatches) {
case 3:
this.manager.score.update(this.#scoreMap[3]);
break;
case 4:
this.manager.score.update(this.#scoreMap[4]);
break;
case 5:
this.manager.score.update(this.#scoreMap[5]);
break;
default:
this.manager.score.update(this.#scoreMap["combo!"])
break;
}
this.#numberOfMatches = 1;
if (this.manager.score.currentScore >= this.manager.score.goalScore) {
alert(`You won! \nYour score was: ${this.manager.score.currentScore}`)
whichScreen = "select screen";
}
else {
console.log(this.manager.score.currentScore);
console.log(this.manager.score.goalScore);
}
return;
}
#findAllMoving() {
for (let x = 0; x < this._width; x++) {
for (let y = 0; y < this._height; y++) {
if (this._tiles[x][y].normalMoving === true) {
// console.log("something moving");
return true;
}
else {
// console.log("nothing moving");
return false;
}
}
}
}
get tiles() {
return this._tiles;
}
get tileSize() {
return this._tileSize;
}
get matching() {
return this.#matching;
}
set matching(value) {
this.#matching = value;
}
get gravity() {
return this.#gravity;
}
set gravity(value) {
this.#gravity = value;
}
}
class SpecialTileGrid extends TileGrid {
#dummyCucumber;
#dummyBanana;
#realCucumber;
#realBanana;
constructor(width, height, tileSize) {
super(width, height, tileSize);
this.#dummyCucumber = new SpecialTile("komkommer", this._tileSize, 1, 8, normalTileGrid);
this.#dummyBanana = new SpecialTile("bananen", this._tileSize, 5, 8, normalTileGrid);
this.#realCucumber = new SpecialTile("komkommer", this._tileSize, 1, 8, normalTileGrid);
this.#realBanana = new SpecialTile("bananen", this._tileSize, 5, 8, normalTileGrid);
this.#generateTileGrid();
}
draw() {
this.#dummyCucumber.draw();
this.#dummyBanana.draw();
this._tiles[1][8].draw();
this._tiles[5][8].draw();
if (inputHandler.selectedSpecialTile != undefined) {
inputHandler.selectedSpecialTile.draw();
}
}
#generateTileGrid() {
this._tiles = new Array();
for (let x = 0; x < this._width; x++) {
this._tiles[x] = new Array();
for (let y = 0; y < this._height; y++) {
this._tiles[x][y] = null;
}
}
this._tiles[1][8] = this.#realCucumber;
this._tiles[5][8] = this.#realBanana;
}
}
Process abstraction¶
Bij proces abstractie zijn de onderliggende details van een proces verborgen. Al zou je dus een Koffiezetapparaat als voorbeeld nemen, bij een koffiezetapparaat heb je een knop die clean zegt. Deze knop stuurd een command om het apparaat intern schoon te maken. onder de kap, gaat het apparaat nu alerlij dingen schoon maken.
Wij weten één proces maar intern gebeuren er meerdere andere processen die eigenlijk van ons zijn geabstraheerd.(Thorben, Stackify.com)
Process abstraction in CSharp¶
Als voorbeeld in C# hebben we hier de de class DrawStartingCard
Deze method tekende de classen ObstacleCard
, NerfCard
en BuffCard
. Hier zijn dus de onderliggende datails van het proces verborgen, want er gebeurt een process (DrawStartingCards
) die anderen methods (ObstacleCard
, NerfCard
en BuffCard
) weer aan roopt die verborgen zijn.
public class ObstacleCard : Card
{
GameState GameState;
public ObstacleCard(int x, int y, GameState gameState) : base(x, y, gameState)
{
InitializeCard("Obstacle");
card.Position = new Vector2(x, y);
Add(card);
this.GameState = gameState;
}
public override void CardUsed(int TileX, int TileY, string TileID)
{
Console.WriteLine("ObstacleCard used");
CreateObstacleTiles(TileX, TileY, TileID);
Remove(card);
Gamestate.cards.Remove(card);
}
public void CreateObstacleTiles(int TileX, int TileY, string TileID)
{
Tile tile = new(Tile.TileType.O, TileX, TileY, TileID);
tile.Position = new Vector2(TileX, TileY);
GameState.Add(tile);
Console.WriteLine("Create obstacle tiles was looped through");
}
}
Encapsulation¶
Encapsulation betekent het bundelen van gegevens aan de Class. De functies, variabelen en andere stukken code die in deze class zitten kunnen niet beïnvloed worden door anderen classes of buitenstaanders. Dit kan je doen door een class private en protected properties te geven.(knowledgebase.hbo-ict-hva.nl)
Public, private en protected¶
In C# kan je public, private en protected properties hebben. In Javascript kan je ook public en private properties hebben maar is er geen ingebouwd mechanisme om properties protected te verklaren
Public¶
Al heb je public properties en methods dan mogen deze gebruikt worden door alles.
In C# toon je dit aan door er public
ervoor te zetten.
Protected¶
Properties en methods mogen alleen gebruikt worden door de class zelf of door subclasses (child-classes van de parent-class)
In C# Toon je dit aan door er protected
ervoor te zetten.
Private¶
Private properties en methods mogen alleen gebruikt worden door de class zelf, dus ook niet door subclassen.
In C# Toon je dit aan door er private
ervoor te zetten en
in JavaScript met een #
Encapsulation in JavaScript¶
In dit voorbeeld uit de code van het project van blok 2
hebben we hier een class met private properties, deze
worden in JavaScript aangegeven met de #
voor de
properties, namelijk typeMap
, type
, image
, size
en enlarge
.
Deze properties zijn dus nu private en kunnen alleen door
de Tile class gebruikt worden
Een ander voorbeeld van hetzelfde project is in de class CanvasManager. Hier worden ook private properties gebruikt, namelijk de width
en de height
. Deze kunnen dus ook aleen gebruikt worden door de CanvasManager class.
Encapsulation in CSharp¶
Anderen voorbeelden van encapsulation in C# is de protected methode initializeCard
Zoals hier onder te zien is.
public class Card : GameObjectList
{
protected SpriteGameObject card;
public bool IsSelected {get; set;}
//public bool IsSelected { get => isSelected; set => isSelected = value; }
public int StartOffsetX {get; set;}
public int StartOffsetY {get; set;}
protected readonly GameState Gamestate;
protected readonly InputHelper inputHelper;
public Card(int x, int y, GameState gameState) : base()
{
//creates a card with an x & y offset, position and image
StartOffsetX = x;
StartOffsetY = y + 50;
Gamestate = gameState;
inputHelper = new InputHelper();
}
protected void InitializeCard(string CardTypeName)
{
card = new SpriteGameObject($"Images/Cards/{CardTypeName}", 0, $"{CardTypeName}");
}
//checks whether the mouse is inside the collision box (image) of a card
public bool CardMouseCollision(Vector2 Mouse)
{
return card.BoundingBox.Contains(Mouse);
}
public virtual void CardUsed(int TileX, int TileY, string TileID)
{
Console.WriteLine("Card used");
Gamestate.cards.Remove(card);
}
}
}
Inherintance¶
Inheritance is dat je een klasse uit een andere klasse afleiden voor een hiërarchie van klassen die properties en methods delen.(Thorben, stackify.com)
Inheritance in JavaScript¶
In JavaScript kan je dit aan tonen met extend
. Door extend
te gebruiken neemt de child class alle methods over en door super
te gebruiken bij de constructor neem je de methods over van de parent class.
class SpecialTile extends Tile {
#offset
#defaultCucumberPosition;
#defaultBananaPosition;
constructor(type, size, x, y) {
super(type, size, x, y);
this.#defaultCucumberPosition = createVector(1, 8).mult(this.size);
this.#defaultBananaPosition = createVector(5, 8).mult(this.size);
this.#offset = createVector(
(size + this._resizeOffset) / 2,
(size + this._resizeOffset) / 2
Inheritance in CSharp¶
Inheritance in C# kan je aantonen met het :
symbool
In het voorbeeld hieronder inherit de class Knight
van de class Piece
. De class Knight
krijgt nu alle properties en methods van de class piece
, mits deze public of protected zijn.
Polymorphism¶
Polymorphism betekent dat de geinherited class methods overwrite die de main class aan hem doorgeeft.(.w3schools.com)
In het voorbeeld hier onder uit C# staat een class genaamd Pawn
, deze Pawn
class heeft geinherit van de class Piece
.
Door middel van de override
keyword overwrite deze child class de movement van de parent class.
class Pawn : Piece
{
public Pawn(string color, Tile tile) : base("Pawn", color, tile.Y, tile.X, "")
{
}
public override bool GetPossibleMoves(Tile currentTile, Tile targetTile)
{
Console.WriteLine("Pawn Movement");
int direction = (GameState.CurrentTeam.TeamId == "White") ? 1 : -1;
if (currentTile.X == targetTile.X && currentTile.Y + direction == targetTile.Y && targetTile.OccupyingPiece == null)
{
return true;
}
if ((currentTile.Y + direction == targetTile.Y) &&
(currentTile.X + 1 == targetTile.X || currentTile.X - 1 == targetTile.X) &&
targetTile.OccupyingPiece != null &&
targetTile.OccupyingPiece.Color != this.Color)
{
return true;
}
return false;
}
}
Conslusie¶
Ik heb erg mijn best gedaan op het maken van deze opdracht. Ik ben vooral zelf op onderzoek gegaan naar bronnen en informatie over OOP om zelf zoveel mogelijk ervan te leren, maar er waren ook punten dat ik er zelf niet uit kwam.
Een voorbeeld hiervan is dat ik een beetje vastliep bij abstraction, het concept Procces abstraction snapte ik niet. Ik had er een idee van, maar ik was niet zeker of de betekenis die ik in mijn hoofd had wel de juiste was. Ik heb toen aan Aram gevraagd of hij mij hierbij kon helpen. Toen we er samen ook niet uitkwamen heb ik de betekenis aan Jur gevraagd en welke voorbeelden ik hiervoor zou kunnen gebruiken. Hij zei dat bij process abstractie de onderliggende details van een proces zijn verborgen. Hierbij heeft hij het voorbeeld gebruikt van een koffiezetapparaat.
Ik heb verder nog meer hulp aan mede-studenten gevraagd. Toen ik klaar was met het maken van de opdracht heb ik aan Sed en Noah gevraagd of zij hem nog konden doorlezen en mij feedback kunnen geven over de uitleg en voorbeelden die ik heb gebruikt. Verder hebben zij ook voor spel- en grammaticafouten gekeken. De feedback die ze mij hebben gegeven, heb ik weer meegenomen in het verbeteren van de opdracht.
Hierna heb ik deze opdracht ook nog laten doorlezen door een student mentor, namelijk Nick. Hij heeft mij meerderen feedbackpunten gegven die ik weer heb verwerkt, verder heeft hij me oop beoordeeld op K5 met deze opdracht als bewijs.
Verder heb ik ervoor gekozen om zoveel mogelijke voorbeelden uit JavaScript én C# te gebruiken. Ik had aan Mike gevraagd of ik C# of JavaScript moest gebruiken, en hij zei dat ik mocht kiezen welke ik wilde gebruiken voor deze opdracht. Ik heb ervoor gekozen om ze allebei te gebruiken, zodat ik zo veel mogelijk uit deze opdracht haal.
Het is natuurlijk vervelend om een extra opdracht te maken naast het normale schoolwerk, maar ik heb veel geleerd van deze opdracht. Er zijn dingen waar ik eerst nog niet veel vanaf wist, zoals waarom ik een property private zou gebruiken en wat nou het verschil is tussen abstraction en encapsulation. Deze vragen zou ik nu wél kunnen beantwoorden.