├── .assets ├── template_end.html ├── template.html └── style.css ├── .markdownlint.json ├── .gitignore ├── labs ├── resources │ └── GPoAD.pdf ├── figures │ ├── vscode-run.png │ └── vscode-launchconfig.png ├── images │ ├── lab11 │ │ ├── proxy.png │ │ ├── proxy2.png │ │ ├── component.png │ │ ├── jsonFormat.png │ │ └── tictactoe.png │ ├── lab09 │ │ ├── lab09_billing.png │ │ ├── lab09_project_select.png │ │ └── lab09_view_all_products.png │ └── lab06 │ │ ├── lab06_test_example.png │ │ ├── lab06_jacoco_report.png │ │ └── lab06_test_side_panel.png ├── lab12.md ├── lab13.md ├── lab02.md ├── lab08.md ├── lab09.md ├── lab10.md ├── lab06.md ├── lab03.md ├── lab07.md ├── lab04.md ├── git-basics.md ├── lab05.md └── lab11.md ├── examples └── lect02simulation.zip ├── previous-labs ├── images │ ├── lab10 │ │ ├── proxy.png │ │ ├── proxy2.png │ │ ├── component.png │ │ ├── tictactoe.png │ │ └── jsonFormat.png │ ├── lab12 │ │ ├── details.png │ │ ├── select-vm.png │ │ ├── create-a-vm.png │ │ ├── select-traffic.png │ │ └── lab13-vm-instances.png │ ├── lab05 │ │ └── Rec05_UML.jpg │ ├── lab11 │ │ └── lifecycle.png │ ├── lab03 │ │ ├── lab03_jacoco_report.png │ │ ├── lab03_test_example.png │ │ └── lab03_test_side_panel.png │ ├── lab08 │ │ ├── lab08_project_select.png │ │ └── lab08_select_billing.png │ └── lab04 │ │ └── blackjack_object_problem.jpg ├── lab14.md ├── f23-lab13.md ├── lab02.md ├── lab08.md ├── lab03.md ├── lab05.md ├── lab09.md ├── lab11.md ├── f23-lab11.md ├── f23-lab10.md ├── lab12.md ├── git-basics.md ├── lab07.md ├── lab06.md ├── f23-lab12.md ├── lab10.md ├── lab13.md └── lab01.md ├── quizzes └── 07-design-critique │ ├── 07-design-critique.pdf │ └── 07-design-critique.tex ├── .github └── workflows │ └── publish.yml ├── labs.md ├── learninggoals.html ├── assignments ├── hw3.md └── hw5.md └── previous-assignments └── hw2.md /.assets/template_end.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD033": false, 3 | "MD013": false 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.aux 3 | *.fdb_latexmk 4 | *.fls 5 | *.log 6 | 7 | -------------------------------------------------------------------------------- /labs/resources/GPoAD.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/resources/GPoAD.pdf -------------------------------------------------------------------------------- /labs/figures/vscode-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/figures/vscode-run.png -------------------------------------------------------------------------------- /labs/images/lab11/proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab11/proxy.png -------------------------------------------------------------------------------- /labs/images/lab11/proxy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab11/proxy2.png -------------------------------------------------------------------------------- /examples/lect02simulation.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/examples/lect02simulation.zip -------------------------------------------------------------------------------- /labs/images/lab11/component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab11/component.png -------------------------------------------------------------------------------- /labs/images/lab11/jsonFormat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab11/jsonFormat.png -------------------------------------------------------------------------------- /labs/images/lab11/tictactoe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab11/tictactoe.png -------------------------------------------------------------------------------- /labs/images/lab09/lab09_billing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab09/lab09_billing.png -------------------------------------------------------------------------------- /labs/figures/vscode-launchconfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/figures/vscode-launchconfig.png -------------------------------------------------------------------------------- /previous-labs/images/lab10/proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab10/proxy.png -------------------------------------------------------------------------------- /previous-labs/images/lab10/proxy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab10/proxy2.png -------------------------------------------------------------------------------- /previous-labs/images/lab12/details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab12/details.png -------------------------------------------------------------------------------- /labs/images/lab06/lab06_test_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab06/lab06_test_example.png -------------------------------------------------------------------------------- /previous-labs/images/lab05/Rec05_UML.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab05/Rec05_UML.jpg -------------------------------------------------------------------------------- /previous-labs/images/lab10/component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab10/component.png -------------------------------------------------------------------------------- /previous-labs/images/lab10/tictactoe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab10/tictactoe.png -------------------------------------------------------------------------------- /previous-labs/images/lab11/lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab11/lifecycle.png -------------------------------------------------------------------------------- /previous-labs/images/lab12/select-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab12/select-vm.png -------------------------------------------------------------------------------- /labs/images/lab06/lab06_jacoco_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab06/lab06_jacoco_report.png -------------------------------------------------------------------------------- /labs/images/lab06/lab06_test_side_panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab06/lab06_test_side_panel.png -------------------------------------------------------------------------------- /labs/images/lab09/lab09_project_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab09/lab09_project_select.png -------------------------------------------------------------------------------- /previous-labs/images/lab10/jsonFormat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab10/jsonFormat.png -------------------------------------------------------------------------------- /previous-labs/images/lab12/create-a-vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab12/create-a-vm.png -------------------------------------------------------------------------------- /labs/images/lab09/lab09_view_all_products.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/labs/images/lab09/lab09_view_all_products.png -------------------------------------------------------------------------------- /previous-labs/images/lab12/select-traffic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab12/select-traffic.png -------------------------------------------------------------------------------- /previous-labs/images/lab03/lab03_jacoco_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab03/lab03_jacoco_report.png -------------------------------------------------------------------------------- /previous-labs/images/lab03/lab03_test_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab03/lab03_test_example.png -------------------------------------------------------------------------------- /previous-labs/images/lab12/lab13-vm-instances.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab12/lab13-vm-instances.png -------------------------------------------------------------------------------- /quizzes/07-design-critique/07-design-critique.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/quizzes/07-design-critique/07-design-critique.pdf -------------------------------------------------------------------------------- /previous-labs/images/lab03/lab03_test_side_panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab03/lab03_test_side_panel.png -------------------------------------------------------------------------------- /previous-labs/images/lab08/lab08_project_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab08/lab08_project_select.png -------------------------------------------------------------------------------- /previous-labs/images/lab08/lab08_select_billing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab08/lab08_select_billing.png -------------------------------------------------------------------------------- /previous-labs/images/lab04/blackjack_object_problem.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CMU-17-214/f2024/HEAD/previous-labs/images/lab04/blackjack_object_problem.jpg -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish-gh-pages 2 | 3 | on: 4 | push: 5 | branch: main 6 | 7 | jobs: 8 | gh-pages: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: Prepare _site 15 | run: | 16 | echo generate main html page in _site/ 17 | mkdir _site 18 | 19 | - name: Generate main page 20 | run: | 21 | cp .assets/template.html _site/index.html 22 | cp .assets/style.css _site/ 23 | npx marked@12.0.2 --gfm -i README.md >> _site/index.html 24 | cat .assets/template_end.html >> _site/index.html 25 | mkdir _site/assignments 26 | cp learninggoals.html _site/ 27 | 28 | - name: Push to gh-pages 29 | run: | 30 | git clone --quiet --branch gh-pages --depth 1 https://github.com/${{ github.repository }}.git .gh-pages 31 | rm -rf .gh-pages/* 32 | mv _site/* .gh-pages 33 | cd .gh-pages 34 | git add . 35 | touch .nojekyll 36 | git add .nojekyll 37 | git config --local user.email "jlacomis@cmu.edu" 38 | git config --local user.name "GitHub Action" 39 | git commit --allow-empty -m "Update gh-pages for ${{ github.sha }}" 40 | git push https://$GITHUB_ACTOR:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:gh-pages --force --follow-tags -v 41 | -------------------------------------------------------------------------------- /.assets/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 17-214: Principles of Software System Construction 8 | 9 | 10 | 13 | 14 | 15 | 16 | 36 | 37 |
38 | 39 | -------------------------------------------------------------------------------- /quizzes/07-design-critique/07-design-critique.tex: -------------------------------------------------------------------------------- 1 | \documentclass{exam} 2 | 3 | \begin{document} 4 | 5 | \makebox[0.75\textwidth]{Name:\enspace\hrulefill} 6 | 7 | \vspace{10mm} 8 | \makebox[0.75\textwidth]{Andrew ID:\enspace\hrulefill} 9 | 10 | \section*{Trouble Rules:} 11 | 12 | 2-4 players are trying to move their pieces from their home to their finish 13 | zone. Players roll a D6 and move their pieces clockwise, rolling a 6 lets them 14 | roll again. To exit their home zone, they must roll a 6 and move a piece from 15 | their home to their start position. Landing on an opponent's piece sends it back 16 | to the opponent's home zone. Players may not have two of their pieces in the 17 | same position. Exact rolls are required when moving to the finish zone. The 18 | first player to have all of their pieces in their own finish zone is the winner. 19 | 20 | \begin{questions} 21 | \question Circle the nouns and verbs in the above description. 22 | 23 | \question Draw a domain model using the verbs and nouns that you circled. 24 | \vspace{\stretch{1}} 25 | 26 | \question Draw a system sequence diagram for the interaction \emph{player 27 | takes a turn}. 28 | \vspace{\stretch{1}} 29 | \clearpage 30 | 31 | \question Draw an object model for this game. 32 | \vspace{\stretch{1}} 33 | 34 | \question Draw an interaction diagram for this game. 35 | \vspace{\stretch{1}} 36 | \end{questions} 37 | \end{document} -------------------------------------------------------------------------------- /labs/lab12.md: -------------------------------------------------------------------------------- 1 | # Lab 12: APIs 2 | 3 | ## Context 4 | This lab will test your knowledge of good API design principles. For this lab you will identify and fix API design principle violations inside a repository containing 3 different APIs 5 | 6 | ## Deliverables 7 | - [ ] Fix an API design principle violation in the DirManager package 8 | - [ ] Fix an API design principle violation in the Library package 9 | - [ ] Fix an API design principle violation in the Weather package 10 | 11 | ## Instructions 12 | Clone the repository from: https://github.com/CMU-17-214/f24-lab12 13 | 14 | Inside the repository you will find three different APIs: DirManager, Library, and Weather. For each of these, you should identify the flaw, update the code, and also update the documentation to match the code that you corrected. You will get full points for each of them if you are able to both identify and fix the flaws. 15 | 16 | ## API Design principles 17 | Here is a list of general API design principles. Each of the violations we have included in this lab correspond to at least one of them. 18 | ![General API Design principles](resources/GPoAD.pdf) 19 | 20 | ## Hints 21 | DirManager is an API designed for managing directories. The design of the `newDirectory` method in the `Manager` class has a flaw that should be identified and fixed. _For this specific flaw_ you do not need to worry about creating new objects, feel free to use them as if they already existed. 22 | 23 | Library is an API designed for managing user accounts in a library system. The design of the `getBooks` method in the `LibraryAccount` API has a flaw. 24 | 25 | Weather is an API designed for interacting with the weather at a specific location. In this case, the `setLengthScale` method has an API design flaw. You may also need to update the `getRainfall` method as well. -------------------------------------------------------------------------------- /labs/lab13.md: -------------------------------------------------------------------------------- 1 | # Lab 13 - Design Pattern Review 2 | 3 | In this recitation, you will revisit three crucial design patterns: **Proxy**, **Composite**, and **Decorator**. For each pattern, your task is to articulate key aspects, discuss why they are beneficial or problematic, and demonstrate their use in UML diagram in the context of *Santorini's God Cards*. 4 | 5 | ## Deliverables 6 | 7 | - [ ] Fill out the **Proxy** pattern template and answer follow-up questions of the TA 8 | - [ ] Fill out the **Composite** pattern template and answer follow-up questions of the TA 9 | - [ ] Fill out the **Decorator** pattern template and answer follow-up questions of the TA 10 | 11 | ## Introduction 12 | 13 | Throughout the semester, we've delved into many commonly used design patterns, including **Proxy**, **Composite**, **Decorator**, **Strategy**, **Template**, **Observer**, and **Adapter**. 14 | 15 | In this lab, we will focus on the first three. 16 | 17 | For each design pattern, you are expected to provide information in five sections: 18 | 19 | - **Description**: Define the key characteristics that distinguish the pattern from others. 20 | - **Pros**: Why should you use this pattern? What specific problems does it solve and what design principles does it support? 21 | - **Cons**: Why might you want to avoid this pattern? What design challenges or complications could it introduce? 22 | - **UML Diagram**: Draw a UML object model for the pattern. 23 | - **Example**: Reflect on your past programming experiences where this pattern could have improved your solution. If you can't think of a personal example, describe a scenario where using this pattern would have made the solution worse. 24 | 25 | ## Instructions 26 | 27 | ### Download the cheatsheat 28 | 29 | Create a copy of the template at 30 | 31 | ### Tips 32 | 33 | - Strive to devise your explanations before consulting external sources. 34 | - While you are only required to explain three design patterns to the TA, feel free to continue filling in the information for the remaining patterns and seek clarification or assistance from the TA if needed. 35 | -------------------------------------------------------------------------------- /previous-labs/lab14.md: -------------------------------------------------------------------------------- 1 | # Lab 14 - Design Pattern Review 2 | 3 | In this recitation, you will revisit three crucial design patterns: **Strategy**, **Template**, and **Decorator**. For each pattern, your task is to articulate key aspects, discuss scenarios where it is beneficial, highlight situations where it might not be the best choice, and demonstrate their use in UML diagram in the context of *Santorini's God Cards*. 4 | 5 | 6 | ## Deliverables 7 | - [ ] Fill out the **Strategy** pattern template and answer follow-up questions of the TA 8 | - [ ] Fill out the **Template** pattern template and answer follow-up questions of the TA 9 | - [ ] Fill out the **Decorator** pattern template and answer follow-up questions of the TA 10 | 11 | ## Introduction 12 | Throughout the semester, we've delved into many commonly used design patterns, including **Strategy**, **Template**, **Decorator**, **Composite**, **Observer**, **Proxy**, and **Adapter**. 13 | 14 | In this lab, we will focus on the first three. 15 | 16 | For each design pattern, you are expected to provide information in four sections: 17 | 18 | - **Description**: Define the key characteristics that distinguish the pattern from others. 19 | - **Pros**: Explain when and why you would choose this pattern. Focus on its advantages in terms of design principles and coding styles. 20 | - **Cons**: Identify scenarios where choosing this pattern might be suboptimal. Focus on what makes it less preferable compared to alternative choices. 21 | - **UML Diagram/Code snippet**: Draw an excerpt of a UML object model illustrating how you could use the design pattern to implement God Cards in Santorini. The model should show concrete classes that are plausible in the game, but an excerpt with only a small subset of methods or fields is fine, as long as it demonstrates the pattern. 22 | 23 | 24 | ## Instructions 25 | 26 | ### Download the cheatsheat 27 | 28 | 1. Create a copy of the template at https://docs.google.com/document/d/1o-j6jTDt1VLfUzJaF_kp-3blUSpXp-U7BGSPdN4vt08/edit?usp=sharing 29 | 30 | ### Tips 31 | 32 | - Strive to devise your explanations before consulting external sources. 33 | - While you are only required to explain three design patterns to the TA, feel free to continue filling in the information for the remaining patterns and seek clarification or assistance from the TA if needed. 34 | -------------------------------------------------------------------------------- /previous-labs/f23-lab13.md: -------------------------------------------------------------------------------- 1 | # Lab 13 - Design Pattern Review 2 | 3 | In this recitation, you will revisit three crucial design patterns: **Strategy**, **Template**, and **Decorator**. For each pattern, your task is to articulate key aspects, discuss scenarios where it is beneficial, highlight situations where it might not be the best choice, and demonstrate their use in UML diagram in the context of *Santorini's God Cards*. 4 | 5 | 6 | ## Deliverables 7 | - [ ] Fill out the **Strategy** pattern template and answer follow-up questions of the TA 8 | - [ ] Fill out the **Template** pattern template and answer follow-up questions of the TA 9 | - [ ] Fill out the **Decorator** pattern template and answer follow-up questions of the TA 10 | 11 | ## Introduction 12 | Throughout the semester, we've delved into many commonly used design patterns, including **Strategy**, **Template**, **Decorator**, **Composite**, **Observer**, **Proxy**, and **Adapter**. 13 | 14 | In this lab, we will focus on the first three. 15 | 16 | For each design pattern, you are expected to provide information in four sections: 17 | 18 | - **Description**: Define the key characteristics that distinguish the pattern from others. 19 | - **Pros**: Explain when and why you would choose this pattern. Focus on its advantages in terms of design principles and coding styles. 20 | - **Cons**: Identify scenarios where choosing this pattern might be suboptimal. Focus on what makes it less preferable compared to alternative choices. 21 | - **UML Diagram/Code snippet**: Draw an excerpt of a UML object model illustrating how you could use the design pattern to implement God Cards in Santorini. The model should show concrete classes that are plausible in the game, but an excerpt with only a small subset of methods or fields is fine, as long as it demonstrates the pattern. 22 | 23 | 24 | ## Instructions 25 | 26 | ### Download the cheatsheat 27 | 28 | 1. Create a copy of the template at https://docs.google.com/document/d/1o-j6jTDt1VLfUzJaF_kp-3blUSpXp-U7BGSPdN4vt08/edit?usp=sharing 29 | 30 | ### Tips 31 | 32 | - Strive to devise your explanations before consulting external sources. 33 | - While you are only required to explain three design patterns to the TA, feel free to continue filling in the information for the remaining patterns and seek clarification or assistance from the TA if needed. 34 | 35 | 36 | -------------------------------------------------------------------------------- /labs.md: -------------------------------------------------------------------------------- 1 | # Labs 2 | 3 | This semester, we have weekly labs. Labs introduce exercises to apply concepts from lectures to concrete problems and they often provide concrete suggestions for tooling and notation. 4 | 5 | We release lab assignments several days before the lab sessions on Mondays. Lab assignments are typically intended to take less than one hour of work per week, but they can take longer if you face technical difficulties or struggle with lecture concepts. You should attempt the lab assignment before the lab session, but if you have questions or face problems you can attend the lab session with incomplete work and continue working on it with the help of TAs during the lab session.[^1] Note that you are unlikely to have enough time to complete the work during the lab session if you do not start before the lab session. 6 | 7 | Each lab assignment has one or more concrete deliverables, each worth one point. You get points for labs by showing your work to a TA during the weekly lab session. Typically showing your work involves showing source code, demoing executions, and (verbally) answering a few questions.[^2] We intend labs to be very low stakes – this is your first practical engagement with the material and mistakes are a normal part of the learning process. Deliverables are graded pass/fail on whether they meet the stated requirements. If your solution does not meet the requirements you can continue working on it during the lab session until it does. 8 | 9 | At the end of the lab session, we will discuss possible solutions. 10 | 11 | ## Collaboration policy 12 | 13 | In contrast to homework assignments, we have a very relaxed collaboration policy for labs. You can work together with other students both before the lab session and during the lab session. While we do not recommend it, you may look at other students’ solutions and reference solutions and even copy them. However, you will have to present and explain your solution to the TA on your own. 14 | 15 | 16 | 17 | [^1]: If it takes you more than one hour to complete the lab assignment, we recommend to stop and take your incomplete solution to the lab session where TAs can help you to complete the work. 18 | [^2]: The TA may ask a few questions about your implementation to probe that you understand your work. If deliverables do not require coding or drawing but instead ask to answer a question (e.g., what best practices are violated in a piece of code) we expect that you give the answer verbally to the TA (you are welcome to type out notes to prepare the answer if you like). 19 | -------------------------------------------------------------------------------- /previous-labs/lab02.md: -------------------------------------------------------------------------------- 1 | # Lab 2: Encapsulation 2 | 3 | In this lab you will get familiar with core language features for encapsulation in Java and practice with encapsulation and information hiding. 4 | 5 | 6 | 7 | ## Deliverables 8 | 9 | - [ ] Rewrite the Java implementation to improve encapsulation. The code should hide implementation details with language mechanisms. 10 | - [ ] Adjust the code to use interfaces instead of direct implementations while maintaining functionality. 11 | - [ ] Demonstrate your understanding of good commit practices with the commits solving this encapsulation task. 12 | 13 | 14 | 15 | ## Good Git Practices 16 | 17 | Recall good practices for git and commit messages from the lecture. Good practices help you and other engineers understand your development process. Especially: 18 | 19 | - Make clean, single purpose commits. 20 | - Leave meaningful but concise commit messages. 21 | - Commit early, commit often 22 | - Don’t alter published history 23 | - Don’t commit generated files 24 | 25 | Demonstrate those practices with all commits you do in this lab and also in all future homework assignments. 26 | 27 | 28 | 29 | ## Improving Encapsulation 30 | 31 | Fork and clone this repository: [https://github.com/CMU-17-214/s24-lab02.](https://github.com/CMU-17-214/s24-lab02.git) 32 | 33 | First, get familiar with the source code. Find the entry point, follow imports, and understand classes/types used. Run the code (recall Recitation 1 for instructions). Generally the code is structured as follows: 34 | 35 | - The `shapes/` folder contains the Shape interface and several implementing classes. 36 | - A `Renderer` class takes a `Rectangle` object and provides a `draw` method. 37 | - `Main.java` creates a `Renderer` backed by a `Rectangle` and calls `draw()` on it. 38 | 39 | 40 | 41 | Second, look for problems—no code is perfect, even if it works. In this case, we are looking for issues related to encapsulation & information hiding. Check whether any code is either accessing or depending on information that is not essential to its functioning. To put it differently, could the code be made to work while assuming access to fewer implementation details. *Hints: What type of Shape does a Renderer actually need, in the real world? Does the implementation depend on something more specific, for instance by accessing information it shouldn’t rely on?* 42 | 43 | 44 | 45 | Third, rewrite the code to improve encapsulation and information hiding. Here are some suggestions: 46 | 47 | 1. First, consider what a better design of the shapes/ package would look like: What would a common interface for a shape look like? 48 | 2. Once you introduce the proper interface, you can make the changes to the implementing classes to both (a) implement that interface precisely, and (b) hide *all* information that is not part of the interface. 49 | 3. Finally, find all *uses* of shapes and ensure that they depend only on the interface and not on any internals. Also think about *declaring types:* if you’ve made all the changes correctly, your main function no longer needs to provide Rectangle to Renderer, so it should declare the shapes as Shapes, even if they are *instantiated* as something more specific. 50 | 51 | 52 | 53 | Finally, commit your solution using good commit practices (see our [Git instructions](git-basics.md) if needed). 54 | -------------------------------------------------------------------------------- /labs/lab02.md: -------------------------------------------------------------------------------- 1 | # Lab 2: Encapsulation 2 | 3 | In this lab you will get familiar with core language features for encapsulation in Java and TypeScript and practice with encapsulation and information hiding. 4 | 5 | ## Deliverables 6 | 7 | - [ ] Rewrite the Java implementation to improve encapsulation. The code (a) should program against an interface where possible, (b) should hide all implementation details with language mechanisms, and (c) should still be runnable. 8 | - [ ] Rewrite the TypeScript implementation to improve encapsulation. The code (a) should program against an interface where possible, (b) should hide all implementation details with language mechanisms, and (c) should still be runnable. 9 | - [ ] Demonstrate your understanding of good commit practices with the commits solving this encapsulation task. 10 | 11 | ## Good Git Practices 12 | 13 | Recall good practices for git and commit messages from the lecture. Good practices help you and other engineers understand your development process. Especially: 14 | 15 | - Make clean, single purpose commits 16 | - Leave meaningful but concise commit messages 17 | - Commit early, commit often 18 | - Don’t alter published history 19 | - Don’t commit generated files 20 | 21 | Demonstrate those practices with all commits you do in this lab and also in all future homework assignments. 22 | 23 | ## Improving Encapsulation 24 | 25 | Fork and clone this repository: 26 | 27 | This repository contains equivalent starter code in both Java and TypeScript. You will complete this task in both languages. 28 | 29 | First, get familiar with the source code. Find the entry point, follow imports, and understand classes/types used. Run the code (recall Recitation 1 for instructions). Generally the code is structured as follows: 30 | 31 | - The `shapes/` folder contains the Shape interface and several implementing classes. 32 | - A `Renderer` class takes a `Rectangle` object and provides a `draw` method. 33 | - `Main.java` or `index.ts` creates a `Renderer` backed by a `Rectangle` and calls `draw()` on it. 34 | 35 | Second, look for problems—no code is perfect, even if it works. In this case, we are looking for issues related to encapsulation & information hiding. Check whether any code is either accessing or depending on information that is not essential to its functioning. To put it differently, could the code be made to work while assuming access to fewer implementation details. *Hints: What type of Shape does a Renderer actually need, in the real world? Does the implementation depend on something more specific, for instance by accessing information it shouldn’t rely on?* 36 | 37 | Third, rewrite the code to improve encapsulation and information hiding. Here are some suggestions: 38 | 39 | 1. First, consider what a better design of the shapes/ package would look like: What would a common interface for a shape look like? 40 | 2. Once you introduce the proper interface, you can make the changes to the implementing classes to both (a) implement that interface precisely, and (b) hide *all* information that is not part of the interface. 41 | 3. Finally, find all *uses* of shapes and ensure that they depend only on the interface and not on any internals. Also think about *declaring types:* if you’ve made all the changes correctly, your main function no longer needs to provide Rectangle to Renderer, so it should declare the shapes as Shapes, even if they are *instantiated* as something more specific. 42 | 43 | Finally, commit your solutions (in both languages) using good commit practices (see our [Git instructions](git-basics.md) if needed). 44 | -------------------------------------------------------------------------------- /previous-labs/lab08.md: -------------------------------------------------------------------------------- 1 | # Lab 8: Concurrency 2 | 3 | Homework 5 involves calling external APIs, specifically the [Google Cloud Vision API](https://cloud.google.com/vision?hl=en). This specific API (and many others you will encounter) requires you to set up an account. In this lab, you will set up your environment to work with the Google Cloud API. Since this lab is about environment setup, you may work through any problems you encounter during setup with others, or seek help from the TAs during your lab session. 4 | 5 | ## Deliverables 6 | - [ ] Sign up for an account and successfully make a call to the Google Cloud Vision API. 7 | - [ ] Reimplement the Promise code in the repository as async/await. 8 | - [ ] Identify a reason why async/await is preferred to Promises and explain it to the TA. 9 | 10 | ## Instructions 11 | ### Setting up a Google Cloud project. 12 | 13 | 1. First, download and install the gcloud CLI interface using the instructions [here](https://cloud.google.com/sdk/docs/install). Once you reach the step where you are asked to run `gcloud init`, run it, then continue following the instructions below. 14 | 1. When asked for an account to use, do _not_ use your CMU email address. If you do, you will not be able to redeem the Google Cloud coupon that we provide you. Instead you should use your personal Gmail account, or sign up for a new one. 15 | 1. Create a new "project". This project is used by Google Cloud to organize your resources. This project will be used for both this lab and for Homework 5. 16 | 1. Log in with `gcloud auth login`. 17 | 18 | ### Redeeming your Google Cloud Education Credit Coupon 19 | 1. Click on the Student Coupon Retrieval Link in the assignment posted to Canvas 20 | 1. Verify your *school* email. 21 | 1. Click the redeem link in the email they send you. 22 | 1. In the window that is opened, in the upper-right of the screen **switch to the personal account** you used earlier. At this point you can enter the coupon code from the email. **Make sure that you do redeem the code for a personal gmail account, not your andrew account**, as it will not work for the latter and you might loose the coupon code in the process. If you receive an error that says "You may not have permission to create projects in this organization", double-check that you have switched to the proper account. *You are only able to redeem a code once, if you have difficulty please post privately on Piazza ASAP so that we can try obtain a new one*. 23 | 24 | ### Enabling billing for your project 25 | 1. Open a web browser and [sign in to the Google Cloud console](https://console.cloud.google.com) with your personal account. 26 | 1. Select the project you just created in the box in the upper-left corner of the screen (here, the project I created is called "cmu17-214"): 27 | 28 | ![lab08_project_select](images/lab08/lab08_project_select.png) 29 | 30 | 1. Open the context menu to the left of the "Google Cloud" logo, expand the drop-down that says "More Poducts", and select Billing: 31 | 32 | ![lab08_select_billing](images/lab08/lab08_select_billing.png) 33 | 34 | 1. You will get a screen that says "This project has no billing account". On this page click "Link A Billing Account". 35 | 36 | 1. In the popup, select the new billing account from the dropdown and select "Set Account". 37 | 38 | ### Enabling the Cloud Vision API 39 | 40 | 1. Enable the Google Cloud Vision API by following [this link](https://console.cloud.google.com/flows/enableapi?apiid=vision.googleapis.com) and following the prompts. 41 | 42 | ### Run and modify code 43 | 44 | 1. Clone the template repository and follow the directions in the README. 45 | -------------------------------------------------------------------------------- /labs/lab08.md: -------------------------------------------------------------------------------- 1 | # Lab 08 - Java Parallelism 2 | 3 | ## Deliverables 4 | 5 | - [ ] Correctly implement a thread-safe unbounded blocking queue. 6 | - [ ] Modify the hash map implementation to make it thread-safe. 7 | - [ ] Describe to the TA why you needed to add synchronization at the specific locations in the hash map implementations. 8 | 9 | ## Instructions 10 | 11 | Clone the repository from [https://github.com/CMU-17-214/f24-lab08](https://github.com/CMU-17-214/f24-lab08). Run `mvn install` to get started. 12 | 13 | In the `src` directory you will find: 14 | 15 | 1. The `edu.cmu.cs.cs214.rec08.queue` package, which provides a `SimpleQueue` interface and an incomplete queue implementation. 16 | 1. The `edu.cmu.cs.cs214.rec08.map` package, which provides a `SimpleHashMap` class. 17 | 1. Various test files in a corresponding package in the `test` directory. These can be run with `mvn test`. Note that these are expected to fail at this point. 18 | 19 | The queue implementation provided is "blocking". This means that its methods can pause (without computation) for an arbitrary amount of time. For example, a method that acquires a lock is likely a blocking method if other parts of the program hold the same lock. 20 | 21 | Your task is to use primitive Java synchronization to implement a correct unbounded blocking queue from our incomplete implementation, and fix the race conditions in `SimpleHashMap`, which is currently not thread safe. 22 | 23 | ## Implementing a blocking queue 24 | 25 | An _unbounded blocking queue_ is a normal queue except, if the queue is empty upon a dequeue request, then the request is blocked until an element is enqueued by another thread. This behavior is different from the standard `java.util` queue implementations, which either return `null` or throw a `NoSuchElementException` if the queue is empty. In an unbounded blocking queue, the dequeue method will always return a valid element from the queue, although the dequeueing thread might wait arbitrarily long to dequeue an element. 26 | 27 | The `edu.cmu.cs.cs214.rec08.queue.UnboundedBlockingQueue` is not yet thread safe; if multiple threads access the same queue concurrently, race conditions can occur and you might obtain unexpected results. 28 | 29 | To complete this part of the lab you should: 30 | 31 | 1. In the `src/test/main` folder, we have provided an `edu.cmu.cs.rec08.queue` test package that tests for the desired behavior of an unbounded blocking queue. Run the tests and understand their expected behavior. These tests will initially fail because the `UnboundedBlockingQueue` as given, is not thread safe and does not block when a thread attempts to dequeue from an empty queue. 32 | 1. Using basic Java synchronization and the `wait` and `notify` methods, eliminate race conditions in the `UnboundBlockingQueue` and make it a correct unbounded blocking queue. In other words, enqueueing an element should always succeed immediately. An attempt to dequeue from an empty queue, however, should block until an element has been enqueued by another thread. To simplify you implementation, prevent race conditions by allowing only one thread to enqueue or dequeue at a time. Use the provided JUnit tests to evaluate the correctness of your implementation. Look at the sample concurrency code from the lectures for more details. 33 | 34 | ## Implementing a thread safe concurrent hash map 35 | 36 | In the `edu.cmu.cs.cs214.rec08.map` package we have provided a `SimpleHashMap` class that is currently not thread safe. Your task is to use primitive Java synchronization to make the implementation thread safe. When you have finished, show the TA your work and explain why synchronization was required where you used it. 37 | -------------------------------------------------------------------------------- /labs/lab09.md: -------------------------------------------------------------------------------- 1 | # Lab 9: Concurrency 2 | 3 | Homework 5 involves calling external APIs, specifically the [Google Cloud Vision API](https://cloud.google.com/vision?hl=en). This specific API (and many others you will encounter) requires you to set up an account. In this lab, you will set up your environment to work with the Google Cloud API. Since this lab is about environment setup, you may work through any problems you encounter during setup with others, or seek help from the TAs during your lab session. 4 | 5 | ## Deliverables 6 | 7 | - [ ] Sign up for an account and successfully make a call to the Google Cloud Vision API. 8 | - [ ] Reimplement the Promise code in the repository as async/await. 9 | - [ ] Identify a reason why async/await is preferred to Promises and explain it to the TA. 10 | 11 | ## Instructions 12 | 13 | ### Setting up a Google Cloud project 14 | 15 | 1. First, download and install the gcloud CLI interface using the instructions [here](https://cloud.google.com/sdk/docs/install). Once you reach the step where you are asked to run `gcloud init`, run it, then continue following the instructions below. 16 | 1. When asked for an account to use, do _not_ use your CMU email address. If you do, you will not be able to redeem the Google Cloud coupon that we provide you. Instead you should use your personal Gmail account, or sign up for a new one. 17 | 1. Create a new "project". This project is used by Google Cloud to organize your resources. This project will be used for both this lab and for Homework 5. 18 | 1. Log in with `gcloud auth login`. 19 | 1. Set the default application authentication with `gcloud auth application-default login`. 20 | 21 | ### Redeeming your Google Cloud Education Credit Coupon 22 | 23 | 1. Click on the Student Coupon Retrieval Link in the assignment posted to Canvas 24 | 1. Verify your _school_ email. 25 | 1. Click the redeem link in the email they send you. 26 | 1. In the window that is opened, in the upper-right of the screen **switch to the personal account** you used earlier. At this point you can enter the coupon code from the email. **Make sure that you do redeem the code for a personal gmail account, not your andrew account**, as it will not work for the latter and you might loose the coupon code in the process. If you receive an error that says "You may not have permission to create projects in this organization", double-check that you have switched to the proper account. _You are only able to redeem a code once, if you have difficulty please post privately on Piazza ASAP so that we can try obtain a new one_. 27 | 28 | ### Enabling billing for your project 29 | 30 | 1. Open a web browser and [sign in to the Google Cloud console](https://console.cloud.google.com) with your personal account. 31 | 1. Select the project you just created in the box in the upper-left corner of the screen (here, the project I created is called "cmu17-214"): 32 | 33 | ![lab09_project_select](images/lab09/lab09_project_select.png) 34 | 35 | 1. Open the context menu to the left of the "Google Cloud" logo and click the "VIEW ALL PRODUCTS" button at the bottom. 36 | 37 | ![lab09_view_all_products](images/lab09/lab09_view_all_products.png) 38 | 39 | 1. Click the "Billing" link under "Management". 40 | 41 | ![lab09_billing](images/lab09/lab09_billing.png) 42 | 43 | 1. You will get a screen that says "This project has no billing account". On this page click "Link A Billing Account". 44 | 45 | 1. In the popup, select the new billing account from the dropdown and select "Set Account". 46 | 47 | ### Enabling the Cloud Vision API 48 | 49 | 1. Enable the Google Cloud Vision API by following [this link](https://console.cloud.google.com/flows/enableapi?apiid=vision.googleapis.com) and following the prompts. 50 | 51 | ### Run and modify code 52 | 53 | 1. Clone the template repository and follow the directions in the README. 54 | -------------------------------------------------------------------------------- /labs/lab10.md: -------------------------------------------------------------------------------- 1 | # Lab 10: Introduction to React.js 2 | 3 | React is a declarative, efficient, and flexible JavaScript library for building interactive and dynamic user interfaces. 4 | It lets you compose complex UIs from small and isolated pieces of code - components. 5 | In this lab, you will learn the fundamentals of React.js and create an interactive quiz application. 6 | 7 | ## Deliverables 8 | - [ ] Separate the core and GUI components. 9 | - [ ] Enhance the UI to highlight the selected answer for a more user appealing experience. 10 | - [ ] Extend the Quiz component to make the "Next Question" button functional. It should move to the next question and display the total score when all questions have been answered. 11 | 12 | ## Instructions 13 | 14 | ### Setup 15 | Fork and clone the Quiz App repository from: [https://github.com/CMU-17-214/f24-lab10](https://github.com/CMU-17-214/f24-lab10) and run 16 | 17 | ``` 18 | npm install 19 | npm start 20 | ``` 21 | ![Local Image](https://github.com/CMU-17-214/f24-lab10/blob/main/src/image/starterPic.png) 22 | 23 | This will start the front-end server. You will be able to see a simple quiz GUI from the link http://localhost:3000/. You can update the front-end code as the server is running in the development mode (i.e., `npm start`). It will automatically recompile and reload. 24 | 25 | In this starter code, you are provided with a Quiz class component. 26 | The initial state includes a sample question, answer options, and a `selectedAnswer` value. 27 | The `handleOptionSelect` function allows selecting an answer option and updates the `selectedAnswer` in the component's state. 28 | The component uses JSX to return HTML-like markup directly, displaying the question, answer options, and the selected answer within the component's return statement. 29 | > JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file. 30 | 31 | --- 32 | 33 | ### Task 1: Core-GUI Separation 34 | You will notice the `Quiz.tsx` file contains both the logic and the graphical user interface (GUI) of the quiz application. 35 | As the project grows, it's best practice to separate the application's core logic from its GUI components. 36 | 37 | We've provided a core implementation at [src/core/QuizCore.ts](https://github.com/CMU-17-214/f24-lab10/blob/main/src/core/QuizCore.ts). This core module encapsulates critical quiz operations. It's designed to manage the quiz's functionality independently of the GUI. Your task is to integrate this core with the user interface `Quiz.tsx`. Ensure that your GUI component correctly reflects the data from the QuizCore. Update your component to display the questions and answer options provided by the core. Take care to observe and update the user's selected options and other state changes effectively. 38 |

39 | ### Task 2: Enhance User Experience 40 | The starter code displays the user’s selection as text directly and your task is to improve the user experience by making it visually engaging. You have the creative freedom to design how the selected option is displayed. 41 | > Hint: Change CSS to highlight or apply a border to the selected option. 42 |

43 | ### Task 3: Manage User Interaction and Scoring 44 | In the initial implementation, the "Next Question" button remains inactive – it neither progresses to the next question nor displays the final score upon completing all the questions. Your task is to make the "Next Question" button functional and display the total score when all questions have been answered. 45 | 46 | When a question is displayed, ensure that the "Next Question" button can take users to the following question. To achieve this, you should check if there is a next question available in the quiz. You can utilize the `hasNextQuestion()` method provided in the core logic. 47 | 48 | When all questions have been answered, "Next Question" button should become "Submit" button, and upon clicking it, display the total score. For simplicity, each question in the quiz is worth a score of 1 if answered correctly. You can utilize the `getScore()` method provided in the core logic. 49 | -------------------------------------------------------------------------------- /learninggoals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17-214: Principles of Software System Construction 7 | 8 | 9 | 12 | 13 | 14 | 15 | 35 | 36 |
37 |

Principles of Software Construction Objects, Design, and Concurrency

38 |
39 | 40 |
41 |

Learning Goals

After taking this course you should be able to...

42 |
    43 |
  • Understand key concepts of object oriented programming (object identity, dynamic dispatch/polymorphism)
  • 44 |
  • Use modern development tools to design and implement nontrivial programs 45 |
      46 |
    • Write programs of medium complexity
    • 47 |
    • Use standard tools expected of professional developers: IDEs, refactoring, debugging, version control, static analysis, code review
    • 48 |
    • Write simple user interfaces using command line or visual frontends
    • 49 |
    50 |
  • 51 |
  • Design code that is easy to understand, maintain, and reuse 52 |
      53 |
    • Domain modeling, responsibility assignment
    • 54 |
    • Taming complexity: Patterns, types, abstraction, and reducing coupling
    • 55 |
    • Design for change: Information hiding, contracts, subtype polymorphism
    • 56 |
    • Design for reuse: Small scale: Delegation, inheritance, parametric polymorphism (generics) 57 | Immutable data structures
    • 58 |
    • Structuring systems at different scale: methods, classes, modules, subsystems (microservices)
    • 59 |
    • Understand and apply common design patterns (technically belongs to the previous point) 60 |
        61 |
      • Understand the idea behind design patterns
      • 62 |
      • Evaluate when to use design patterns and apply them to solve common design problems
      • 63 |
      • Understand common anti-patterns
      • 64 |
      65 |
    • 66 |
    67 |
  • 68 |
  • Use and design libraries, frameworks, and APIs (design for reuse at scale)
  • 69 |
  • Program confidently with concurrency 70 |
      71 |
    • Challenges and modern solutions and patterns
    • 72 |
    • Basic understanding of distributed systems and RPC, client server, microservice
    • 73 |
    74 |
  • 75 |
  • Assess functional correctness with unit tests 76 |
      77 |
    • Competency in writing unit tests and integration tests
    • 78 |
    • Create tests using a dedicated testing strategy (boundary condition, coverage, …)
    • 79 |
    • Design software to be testable, good test suite design
    • 80 |
    • Build and test automation, CI, test coverage
    • 81 |
    • Testing robustness, integration testing
    • 82 |
    • Ideas in unit testing: TDD, BDD, …
    • 83 |
    • Understand the tradeoffs between formal verification and testing (and type checking and static analysis)
    • 84 |
    85 |
  • 86 |
87 | 88 |
89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /previous-labs/lab03.md: -------------------------------------------------------------------------------- 1 | # Lab 3: Testing 2 | 3 | In this lab you will get familiar with different testing strategies and practice writing good unit tests in Java. 4 | 5 | ## Concepts 6 | **Structural testing vs Specification testing:** Two distinct types of unit testing are specification-based (historically: black-box) testing and structural (white-box) testing. Specification testing is when you write high-level test cases against the specification of a program, without using (or testing) the underlying implementation of the program. In structural testing, your tests are instead tailored to the specific underlying implementation of the code you are testing. 7 | 8 | **Code coverage:** Coverage is the amount of code that has been executed by the tests. There are several coverage metrics, but one common metric line coverage is simply the percentage of lines (or statements) that have been executed by your unit tests. 9 | 10 | ## Deliverables 11 | 12 | - [ ] Using specification testing, write tests for the `LinkedIntQueue` class, then execute them from within the IDE. 13 | - [ ] Use the above tests to find bugs in the `ArrayIntQueue` class. 14 | - [ ] Add tests to achieve 100% line coverage for the `ArrayIntQueue` class, and show coverage results in the IDE or as an HTML report. 15 | - [ ] Describe your experience with the tradeoffs between structural testing and specification testing to your TA. (No written answer is needed.) 16 | 17 | 18 | ## Instructions 19 | 20 | ### Setup 21 | Fork and clone the repo from https://github.com/CMU-17-214/s24-lab03. 22 | The code is set up with JUnit. You can use your IDE to open the folder of Java and run the existing tests with the command in the readme.md. You can also see Appendix 1 for how to run tests in your IDE. 23 | 24 | 25 | ### Testing 26 | For the `LinkedIntQueue` class, use specification testing by refering to the `IntQueue` specification in `IntQueue.java`. 27 | Write additional tests and execute them from within the IDE. 28 | 29 | For the `ArrayIntQueue` class, use structural testing. Specifically test the underlying implementation of the `ArrayIntQueue` class, not just test against the `IntQueue` specification. 30 | 1. Open the Java folder with your IDE. Run the `IntQueueTest` class in the IDE (see readme.txt). Change the `mQueue` variable to `ArrayIntQueue` and run the tests again. Use your IDE to see the line coverage result. See appendix 3 for coverage tooling. 31 | 2. Try to find two bugs in `ArrayIntQueue` by running your tests. Fix each bug that was found. 32 | 3. Write more test cases to achieve 100% line coverage. 33 | 34 | ## Appendix 1: Test Integration in VSCode 35 | The `Test Runner for Java` plugin in VSCode provides great test integration functionality. The testing side panel shows all the tests of the current project. You can also run all tests or a particular test here. 36 | 37 | ![lab03_test_side_panel](images/lab03/lab03_test_side_panel.png) 38 | 39 | After running the test cases, the plugin also shows the failed test cases. Also, you can direct to the failed assertions, and VSCode can show the concrete reasons for the failures. 40 | 41 | ![lab03_test_example](images/lab03/lab03_test_example.png) 42 | 43 | ## Appendix 2: Test Directories For Java 44 | By convention in Maven, test files are placed in a test folder with the path `src/test/java`. You may need to create this directory if it does not exist. (This is useful for homework 2.) In some IDEs, you may need to indicate that this directory contains test files for the IDE to recognize and run the classes. In this directory create the same package structure as in `src/main/java` and place the test class in the same package as the class to be tested. 45 | 46 | ## Appendix 3: Coverage Tools 47 | In Java, we already set up the project to use Jacoco for collecting coverage information. If you run `mvn test` or `mvn site` to execute the tests, it will produce a report in `target/site/jacoco/index.html`. You can check the pom.xml file to see how we enabled this. Open with a browser to view the coverage report. 48 | 49 | Your jacoco report should be similar to this when viewed in the browser. 50 | ![lab03_jacoco_report](images/lab03/lab03_jacoco_report.png) 51 | 52 | In IntelliJ you can run tests with Coverage directly from within your IDE: Right click on test class and select **Run '$classname' with Coverage**; there should be a panel that pops up the right side of the screen showing class coverage. 53 | 54 | -------------------------------------------------------------------------------- /previous-labs/lab05.md: -------------------------------------------------------------------------------- 1 | # Lab 5: Inheritance and Composition 2 | 3 | ## Concepts 4 | **Inheritance vs Composition:** 5 | + Inheritance: Allow one class (Child class) inherits attributes and behaviors from another class (Parent class), promoting code reusability. 6 | + Composition: One class reuses functionality from another class through its public interface, which reduces coupling. 7 | 8 | ## Deliverables 9 | - [ ] Create a subclass of SortedIntList with inheritance that counts how many elements have been added to the list. 10 | - [ ] Create a class that wraps a SortedIntList using a decorator to count how many elements have been added to the list. 11 | - [ ] Discuss questions regarding the tradeoffs and limitations between inheritance and composition with a TA (no written answer needed). 12 | 13 | ## Instructions 14 | 15 | ### Setup 16 | Fork and clone the repo from [https://github.com/CMU-17-214/s24-lab05](https://github.com/CMU-17-214/s24-lab05) 17 | 18 | ## Task Overview 19 | You will examine the strengths and weaknesses of inheritance and composition by using both techniques to add a feature to a ```SortedIntList``` class. The ```SortedIntList``` class is one of a family of integer lists. It is very similar to the ```AbstractIntList```, except it stores its elements in ascending order. 20 | 21 | We want to instrument a ```SortedIntList``` to count how many elements have been added since it was created. (This is not the same as its current size, which is reduced when an element is removed). To provide this functionality ```getTotalAdded```, you should count the number of attempted insertions and also provide an access method to get this count. Your solutions should use inheritance and composition so you can reuse, but not modify, the original ```SortedIntList``` implementation. Please refer to the appendix for the UML diagram. 22 | 23 | 24 | ### Task 1: Instrumentation with inheritance 25 | We have provided an empty ```InheritanceSortedIntList``` class where you should implement an inheritance-based solution. 26 | 27 | > Hints: 28 | > + ```InheritanceSortedIntList``` should extend ```SortedIntList```. 29 | > + The ```SortedIntList``` contains two methods that add elements, ```add``` and ```addAll```. 30 | > + You should override both of these methods to track how many elements have been added. 31 | > + Make sure you check that ```getTotalAdded``` works with both ```add``` and ```addAll```. 32 | 33 | After you have implemented the ```InheritanceSortedIntList``` class, test the instrumentation you just added using tests in ```InheritanceSortedIntListTest``` class. 34 | 35 | ### Task 2: Instrumentation with composition: 36 | We have provided an empty ```DelegationSortedIntList``` class where you should implement your composition-based solution. 37 | 38 | > Hints: 39 | > + Ensure your class implements the ```IntegerList``` interface. 40 | > + Create a private ```SortedIntList``` instance to which you will delegate list-storing functionality. 41 | > + Forward list operations to the ```SortedIntList``` instance. 42 | > + Make sure you check that ```getTotalAdded``` works with both ```add``` and ```addAll```. 43 | > + After you have implemented the ```DelegationSortedIntList``` class, test the instrumentation you just added using tests in ```DelegationSortedIntListTest``` class. 44 | 45 | 46 | Run the tests and make sure your instrumentation passes all the tests. 47 | (You might want to use the ```printList``` helper we provided you and read the documentation for ```addAll``` in the ```AbstractIntList``` class.) 48 | 49 | ### Task 3: Questions on Composition and Inheritance 50 | Evaluate your two implementations for the given problem and answer the following questions: 51 | 1. Which is more dependent on the implementation details of the ```SortedIntList```, composition or inheritance? 52 | 2. If the ```add``` method in ```SortedIntList``` is significantly modified or its behavior changes, which implementation is more likely to break? 53 | 3. What issues does using composition solve that might have been problematic with inheritance? 54 | 4. Based on the provided implementations, when would it be more appropriate to use inheritance and when to use composition? 55 | 56 | 57 | ## Appendix 58 | Take a look at the UML diagram to see what each function should implement. 59 | ![lab04-object-model-problem](images/lab05/Rec05_UML.jpg) 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /labs/lab06.md: -------------------------------------------------------------------------------- 1 | # Lab 6: Testing 2 | 3 | In this lab you will get familiar with different testing strategies and practice writing good unit tests in Java. 4 | 5 | ## Concepts 6 | 7 | **Structural testing vs Specification testing:** Two distinct types of unit testing are specification-based (historically: black-box) testing and structural (white-box) testing. Specification testing is when you write high-level test cases against the specification of a program, without using (or testing) the underlying implementation of the program. In structural testing, your tests are instead tailored to the specific underlying implementation of the code you are testing. 8 | 9 | **Code coverage:** Coverage is the amount of code that has been executed by the tests. There are several coverage metrics, but one common metric line coverage is simply the percentage of lines (or statements) that have been executed by your unit tests. 10 | 11 | ## Deliverables 12 | 13 | - [ ] Using specification testing, write tests for the `LinkedIntQueue` class, then execute them from within the IDE. 14 | - [ ] Use the above tests to find bugs in the `ArrayIntQueue` class. 15 | - [ ] Add tests to achieve 100% line coverage for the `ArrayIntQueue` class, and show coverage results in the IDE or as an HTML report. 16 | - [ ] Describe your experience with the tradeoffs between structural testing and specification testing to your TA. (No written answer is needed.) 17 | 18 | ## Instructions 19 | 20 | ### Setup 21 | 22 | Fork and clone the repo from https://github.com/CMU-17-214/f24-lab06. 23 | The code is set up with JUnit. You can use your IDE to open the folder of Java and run the existing tests with the command in the readme.md. You can also see Appendix 1 for how to run tests in your IDE. 24 | 25 | ### Testing 26 | 27 | For the `LinkedIntQueue` class, use specification testing by refering to the `IntQueue` specification in `IntQueue.java`. 28 | Write additional tests and execute them from within the IDE. 29 | 30 | For the `ArrayIntQueue` class, use structural testing. Specifically test the underlying implementation of the `ArrayIntQueue` class, not just test against the `IntQueue` specification. 31 | 32 | 1. Open the Java folder with your IDE. Run the `IntQueueTest` class in the IDE (see REAME.md). Change the `mQueue` variable to `ArrayIntQueue` and run the tests again. Use your IDE to see the line coverage result. See appendix 3 for coverage tooling. 33 | 2. Try to find two bugs in `ArrayIntQueue` by running your tests. Fix each bug that was found. 34 | 3. Write more test cases to achieve 100% line coverage. 35 | 36 | ## Appendix 1: Test Integration in VSCode 37 | 38 | The `Test Runner for Java` plugin in VSCode provides great test integration functionality. The testing side panel shows all the tests of the current project. You can also run all tests or a particular test here. 39 | 40 | ![lab06_test_side_panel](images/lab06/lab06_test_side_panel.png) 41 | 42 | After running the test cases, the plugin also shows the failed test cases. Also, you can direct to the failed assertions, and VSCode can show the concrete reasons for the failures. 43 | 44 | ![lab06_test_example](images/lab06/lab06_test_example.png) 45 | 46 | ## Appendix 2: Test Directories For Java 47 | 48 | By convention in Maven, test files are placed in a test folder with the path `src/test/java`. You may need to create this directory if it does not exist. (This is useful for homework 3.) In some IDEs, you may need to indicate that this directory contains test files for the IDE to recognize and run the classes. In this directory create the same package structure as in `src/main/java` and place the test class in the same package as the class to be tested. 49 | 50 | ## Appendix 3: Coverage Tools 51 | 52 | In Java, we already set up the project to use Jacoco for collecting coverage information. If you run `mvn test` or `mvn site` to execute the tests, it will produce a report in `target/site/jacoco/index.html`. You can check the pom.xml file to see how we enabled this. Open with a browser to view the coverage report. 53 | 54 | Your jacoco report should be similar to this when viewed in the browser. 55 | ![lab06_jacoco_report](images/lab06/lab06_jacoco_report.png) 56 | 57 | In VSCode you can run tests with Coverage directly from within your IDE: Right click on test class and select **Run '$classname' with Coverage**; there should be a panel that pops up the right side of the screen showing class coverage. 58 | -------------------------------------------------------------------------------- /previous-labs/lab09.md: -------------------------------------------------------------------------------- 1 | # Lab 9: Introduction to React.js 2 | 3 | React is a declarative, efficient, and flexible JavaScript library for building interactive and dynamic user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.In this lab, students will learn the fundamentals of React.js and create an interactive quiz application. 4 | 5 | ## Deliverables 6 | - [ ] Modify the implementation to separate the core and GUI components. 7 | - [ ] Enhance the user interface to indicate the selected answer, providing a more visually appealing user experience 8 | - [ ] Extend the Quiz component to make the "Next Question" button functional. It should move to the next question and display the total score when all questions have been answered. 9 | 10 | ## Instructions 11 | Clone the Quiz App repository from: https://github.com/CMU-17-214/s24-rec09 and run 12 | 13 | ``` 14 | npm install 15 | npm start 16 | ``` 17 | ![Local Image](https://github.com/CMU-17-214/s24-rec09/blob/main/src/image/starterPic.png) 18 | 19 | This will start the front-end server. You will be able to see a simple quiz GUI from the link http://localhost:3000/. You can update the front-end code as the server is running in the development mode (i.e., `npm start`). It will automatically recompile and reload. 20 | 21 | In this starter code, you are provided with a Quiz class component. 22 | The initial state includes a sample question, answer options, and a `selectedAnswer` value. 23 | The `handleOptionSelect` function allows selecting an answer option and updates the `selectedAnswer` in the component's state. 24 | The component uses JSX to return HTML-like markup directly, displaying the question, answer options, and the selected answer within the component's return statement. 25 | > JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file 26 | 27 | ### Core-GUI Separation 28 | In the starter code, you will observe that the `Quiz.tsx` file combines both the logic and the graphical user interface (GUI) of the quiz application. While this might be a convenient starting point, it is generally considered a best practice to separate the core logic of an application from its GUI components. This separation ensures better maintainability, code organization, and flexibility for future improvements. 29 | Therefore, the first task is to practice Core-GUI Separation. For your convenience, We've provided a core implementation for you at [src/core/QuizCore.ts](https://github.com/CMU-17-214/s24-rec09/blob/main/src/core/QuizCore.ts). This core module encapsulates critical quiz operations. It's designed to manage the quiz's functionality independently of the GUI. Your task is to integrate this core with the user interface `Quiz.tsx`. Ensure that your GUI component correctly reflects the data from the QuizCore. Update your component to display the questions and answer options provided by the core. Take care to observe and update the user's selected options and other state changes effectively. 30 | 31 | ### Enhance User Experience 32 | The starter code directly displays the user's current selection. Your task is to enhance the user experience by making is more visually appealing. You have the creative freedom to improve the user interface.One way is to highlight the selected option. When a user clicks on an answer, it should be visually highlighted. 33 | 34 | > Hint: You can consider using CSS to change the background color or apply a border to the selected option 35 | 36 | ### Manage User Interaction and Scoring 37 | In the initial implementation, the "Next Question" button remains inactive – it neither progresses to the next question nor displays the final score upon completing all the questions. Your next task is to enhance the user interaction by making the "Next Question" button functional when appropriate and displaying the total score when all questions have been answered. 38 | 39 | Here's what you need to do: 40 | When a question is displayed, ensure that the "Next Question" button takes users to the following question. To achieve this, you should check if there is a next question available in the quiz. You can utilize the `hasNextQuestion()` method provided in the core logic. 41 | 42 | When all questions have been answered, make a "Submit" button visible, and upon clicking it, display the total score. For simplicity, each question in the quiz is worth a score of 1 if answered correctly. You can utilize the `getScore()` method provided in the core logic. 43 | -------------------------------------------------------------------------------- /labs/lab03.md: -------------------------------------------------------------------------------- 1 | # Lab 3: Inheritance and Delegation 2 | 3 | ## Concepts 4 | **Inheritance vs Delegation:** 5 | + Inheritance: Allow one class (Child class) inherits attributes and behaviors from another class (Parent class), promoting code reusability. 6 | + Delegation: One class delegates duties to another class which reduces coupling. 7 | 8 | ## Deliverables 9 | - [ ] Create a subclass of SortedIntList with inheritance that counts how many elements have been added to the list. 10 | - [ ] Create a class to extend SortedIntList with delegation to count how many elements have been added to the list. 11 | - [ ] Discuss questions regarding the tradeoffs and limitations between inheritance and delegation with a TA (no written answer needed). 12 | 13 | ## Instructions 14 | 15 | ### Setup 16 | Fork and clone the repo from [https://github.com/CMU-17-214/f24-lab03](https://github.com/CMU-17-214/f24-lab03.git) 17 | 18 | The repo has both Java and Typescript codes so feel free to implement in either of the languages you feel comfortable. Please try out the other language in your own time to gain an understanding of inheritance & delegation in both languages. 19 | 20 | ## Task Overview 21 | You will examine the strengths and weaknesses of inheritance and delegation by using both techniques to add a feature to a ```SortedIntList``` class. The ```SortedIntList``` class is one of a family of integer lists. It is very similar to the ```AbstractIntList```, except it stores its elements in ascending order. 22 | 23 | We want to instrument a ```SortedIntList``` to count how many elements have been added since it was created. (This is not the same as its current size, which is reduced when an element is removed). To provide this functionality ```getTotalAdded```, you should count the number of attempted insertions and also provide an access method to get this count. Your solutions should use inheritance and delegation so you can reuse, but not modify, the original ```SortedIntList``` implementation. Please refer to the appendix for the UML diagram. 24 | 25 | 26 | ### Task 1: Instrumentation with inheritance 27 | We have provided an empty ```InheritanceSortedIntList``` class where you should implement an inheritance-based solution. 28 | 29 | > Hints: 30 | > + ```InheritanceSortedIntList``` should extend ```SortedIntList```. 31 | > + The ```SortedIntList``` contains two methods that add elements, ```add``` and ```addAll```. 32 | > + You should override both of these methods to track how many elements have been added. 33 | > + Make sure you check that ```getTotalAdded``` works with both ```add``` and ```addAll```. 34 | 35 | After you have implemented the ```InheritanceSortedIntList``` class, test the instrumentation you just added using tests in ```InheritanceSortedIntListTest``` class. 36 | 37 | ### Task 2: Instrumentation with delegation: 38 | We have provided an empty ```DelegationSortedIntList``` class where you should implement your delegation-based solution. 39 | 40 | > Hints: 41 | > + Ensure your class implements the ```IntegerList``` interface. 42 | > + Create a private ```SortedIntList``` instance for delegation. 43 | > + Delegate list operations to the ```SortedIntList``` instance. 44 | > + Make sure you check that ```getTotalAdded``` works with both ```add``` and ```addAll```. 45 | > + After you have implemented the ```DelegationSortedIntList``` class, test the instrumentation you just added using tests in ```DelegationSortedIntListTest``` class. 46 | 47 | 48 | Run the tests and make sure your instrumentation passes all the tests. 49 | (You might want to use the ```printList``` helper we provided you and read the documentation for ```addAll``` in the ```AbstractIntList``` class.) 50 | 51 | ### Task 3: Questions on Delegation and Inheritance 52 | Evaluate your two implementations for the given problem and answer the following questions: 53 | 1. Which is more dependent on the implementation details of the ```SortedIntList```, delegation or inheritance? 54 | 2. If the ```add``` method in ```SortedIntList``` is significantly modified or its behavior changes, which implementation is more likely to break? 55 | 3. What issues does using delegation solve that might have been problematic with inheritance? 56 | 4. Based on the provided implementations, when would it be more appropriate to use inheritance and when to use delegation? 57 | 58 | 59 | ## Appendix 60 | Take a look at the UML diagram to see what each function should implement. 61 | ![Rec05_UML](https://github.com/user-attachments/assets/d9ee7c69-81cf-4604-be85-baf1d72bdac4) 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /previous-labs/lab11.md: -------------------------------------------------------------------------------- 1 | # Lab 11 - Introduction to Frameworks 2 | 3 | Repo link: https://github.com/CMU-17-214/s24-rec11 4 | 5 | In this recitation, you will create a TicTacToe plug-in for a simple framework that facilitates the implementation of 2D grid games. To make grid game development straightforward, the game plugins must only implement the game’s logic. Everything else (plug-in registration, player management, GUI implementation, etc.) is done by the framework. We hope that this provides a good illustration for the kind of extension mechanisms that may be useful for implementing other extensible systems (e.g., Santorini God Cards). 6 | 7 | ## Deliverables 8 | - [ ] Implement a simple Tic-Tac-Toe plugin, in either Java or TypeScript, and register it with the framework. 9 | - [ ] Discuss what the extension points are in this system and explain why to your TA. 10 | - [ ] Discuss what design pattern is being used here with your TA. 11 | 12 | ## Introduction 13 | A framework provides a set of common functionalities that can be used by plug-ins to build applications. These functionalities typically include: 14 | - A set of predefined functions or classes that can be used to perform common tasks, such as database access, input validation, and session management. 15 | - A set of rules or conventions that dictate how code should be structured and organized within the framework. 16 | - A set of APIs that plug-ins can use to interact with the framework and other plug-ins. 17 | 18 | On the other hand, plug-ins are responsible for implementing specific features or functionality that are not provided by the framework. This can include things like custom user interfaces, business logic, or integration with third-party services. Plug-ins may also be responsible for making certain decisions about how the application should function or behave, such as which database to use or how to handle errors. 19 | 20 | ## The Framework 21 | The core implementation of the framework is located in the core package/directory, a GamePlugin interface, and a GameFramework interface defining the methods Plugins can call on the framework. Grid game plug-ins must implement the GamePlugin interface in order to be registered with the framework. The GamePlugin interface contains several lifecycle methods that are called at various times throughout the period of a game (see the figure below). It also has a few getter methods that the framework will call to obtain the name of the plug-in game, the width/height of the plug-in game’s board, etc. 22 | 23 | ![lifecycle](images/lab11/lifecycle.png) 24 | 25 | Two example plug-ins, “Rock-Paper-Scissors” (a classic grid-based game, seriously) and “Memory”, are already implemented for you in the plugin package/directory. You can start backend and frontend, and then go to http://localhost:3000 to see the behavior. 26 | 27 | ## Instructions 28 | Read the given framework implementation to familiarize yourself with what it provides you, the sample plug-ins to see how you can implement your own plugin, and the documentation for the GamePlugin interface. 29 | 30 | Implement a simple TicTacToe plugin in the plugin package/directory. We have provided you with an implementation of the game TicTacToe in the games package/directory, which you can use in your plugin implementation. 31 | 32 | To register your plugin with the framework, add the fully-qualified class name of your plugin to the edu.cmu.cs.cs214.rec11.framework.core.GamePlugin file in the src/main/resources/META-INF/services/ directory; in App.java, a method called loadPlugins() will use java.util.ServiceLoader which will then use Java reflection to instantiate your plug-in and register it with the framework. 33 | 34 | An implementation completely in TypeScript is provided to you in the typescript branch. Check out the code in src/pluginloader.ts to see how to load plugins in Typescript. Any .js file in the plugin directory is loaded (files created by the compiler from .ts files work fine). If it exports a method “init()” that method is called and expected to return an object implementing the GamePlugin interface. The loading code is fairly straightforward using promises. 35 | 36 | ### Set Up Java ### 37 | Either run the Java backend by using your IDE or by typing 38 | ``` 39 | mvn exec:exec 40 | ``` 41 | in the backend folder. This will start the Java server at http://localhost:8080. 42 | 43 | ### Set Up Typescript ### 44 | In the frontend folder, run 45 | 46 | ``` 47 | npm install 48 | npm start 49 | ``` 50 | 51 | This will start the frontend server at http://localhost:3000. You can update the frontend code as the server is running in the development mode (i.e., npm start). It will automatically recompile and reload. 52 | -------------------------------------------------------------------------------- /previous-labs/f23-lab11.md: -------------------------------------------------------------------------------- 1 | # Lab 11 - Introduction to Frameworks 2 | 3 | Repo link: https://github.com/CMU-17-214/f23-lab11 4 | 5 | In this recitation, you will create a TicTacToe plug-in for a simple framework that facilitates the implementation of 2D grid games. To make grid game development straightforward, the game plugins must only implement the game’s logic. Everything else (plug-in registration, player management, GUI implementation, etc.) is done by the framework. We hope that this provides a good illustration for the kind of extension mechanisms that may be useful for implementing other extensible systems (e.g., Santorini God Cards). 6 | 7 | ## Deliverables 8 | - [ ] Implement a simple Tic-Tac-Toe plugin, in either Java or TypeScript, and register it with the framework. 9 | - [ ] Discuss what the extension points are in this system and explain why to your TA. 10 | - [ ] Discuss what design pattern is being used here with your TA. 11 | 12 | ## Introduction 13 | A framework provides a set of common functionalities that can be used by plug-ins to build applications. These functionalities typically include: 14 | - A set of predefined functions or classes that can be used to perform common tasks, such as database access, input validation, and session management. 15 | - A set of rules or conventions that dictate how code should be structured and organized within the framework. 16 | - A set of APIs that plug-ins can use to interact with the framework and other plug-ins. 17 | 18 | On the other hand, plug-ins are responsible for implementing specific features or functionality that are not provided by the framework. This can include things like custom user interfaces, business logic, or integration with third-party services. Plug-ins may also be responsible for making certain decisions about how the application should function or behave, such as which database to use or how to handle errors. 19 | 20 | ## The Framework 21 | The core implementation of the framework is located in the core package/directory, a GamePlugin interface, and a GameFramework interface defining the methods Plugins can call on the framework. Grid game plug-ins must implement the GamePlugin interface in order to be registered with the framework. The GamePlugin interface contains several lifecycle methods that are called at various times throughout the period of a game (see the figure below). It also has a few getter methods that the framework will call to obtain the name of the plug-in game, the width/height of the plug-in game’s board, etc. 22 | 23 | ![lifecycle](images/lab11/lifecycle.png) 24 | 25 | Two example plug-ins, “Rock-Paper-Scissors” (a classic grid-based game, seriously) and “Memory”, are already implemented for you in the plugin package/directory. You can start backend and frontend, and then go to http://localhost:3000 to see the behavior. 26 | 27 | ## Instructions 28 | Read the given framework implementation to familiarize yourself with what it provides you, the sample plug-ins to see how you can implement your own plugin, and the documentation for the GamePlugin interface. 29 | 30 | Implement a simple TicTacToe plugin in the plugin package/directory. We have provided you with an implementation of the game TicTacToe in the games package/directory, which you can use in your plugin implementation. 31 | 32 | To register your plugin with the framework, add the fully-qualified class name of your plugin to the edu.cmu.cs.cs214.rec09.framework.core.GamePlugin file in the src/main/resources/META-INF/services/ directory; in App.java, a method called loadPlugins() will use java.util.ServiceLoader which will then use Java reflection to instantiate your plug-in and register it with the framework. 33 | 34 | An implementation completely in TypeScript is provided to you in the typescript branch. Check out the code in src/pluginloader.ts to see how to load plugins in Typescript. Any .js file in the plugin directory is loaded (files created by the compiler from .ts files work fine). If it exports a method “init()” that method is called and expected to return an object implementing the GamePlugin interface. The loading code is fairly straightforward using promises. 35 | 36 | ### Set Up Java ### 37 | Either run the Java backend by using your IDE or by typing 38 | ``` 39 | mvn exec:exec 40 | ``` 41 | in the backend folder. This will start the Java server at http://localhost:8080. 42 | 43 | In the frontend folder, run 44 | 45 | ``` 46 | npm install 47 | npm start 48 | ``` 49 | 50 | This will start the frontend server at http://localhost:3000. You can update the frontend code as the server is running in the development mode (i.e., npm start). It will automatically recompile and reload. 51 | 52 | 53 | ### Set Up Typescript ### 54 | 55 | Run 56 | ``` 57 | npm install 58 | npm run compile 59 | npm run serve 60 | ``` 61 | to start the server. 62 | -------------------------------------------------------------------------------- /previous-labs/f23-lab10.md: -------------------------------------------------------------------------------- 1 | # Lab 10 - Testing in the Real World 2 | 3 | This recitation is an introduction to test doubles. 4 | 5 | ## Deliverables 6 | - [ ] Use a fake to test `logIn` 7 | - [ ] Use stubs to test `getRecommendation` 8 | - [ ] Use mocks to test `sendPromoEmail` 9 | 10 | ## Introduction 11 | 12 | In testing, it may sometimes be necessary to use objects or procedures that look and behave like their release-intended counterparts but are actually simplified versions that reduce the complexity and facilitate testing. Objects or procedures meant for production can be too slow, unavailable, expensive, opaque, or non-deterministic. Instead, test doubles are often used. There are multiple types of test doubles, but the most well-known/popular are Fakes, Stubs, and Mocks. 13 | 14 | ### Fakes 15 | 16 | Fakes are fully functional classes with a simplified implementation. Usually, they take some shortcuts and are a simplified version of the real object. We use fakes to avoid interacting directly with objects that are too costly to access during testing, like databases. So, instead of querying our actual database, we use a fully functional in-memory database to simulate the same operations. 17 | 18 | 19 | 20 | ### Stubs 21 | 22 | A stub is an artificial class that returns pre-configured data. We use it to answer calls during tests. Stubs are used when we can't or don’t want to involve objects that would answer with real data or would have undesirable side effects. For example, instead of querying our real database, we may use a stub with predefined data to simulate only the functionality we need. 23 | 24 | 25 | 26 | ### Mocks 27 | 28 | A mock is an instrumented variant of a real class with fine-grained control. We use mocks when we don’t want to invoke expensive production code or when there is no easy way to verify that an intended action was executed. For example, we don't want to send a new email every time we want to test an email system. 29 | 30 | 31 | 32 | These three terms are usually used interchangeably in practice, but there are some subtle differences. You can find plenty of resources online that go into more detail on the differences if you're still unsure what they are (don't worry, even experienced software developers get it [wrong](https://martinfowler.com/articles/mocksArentStubs.html)). 33 | 34 | ## Instructions 35 | 36 | Clone the AndrewWS repository from https://github.com/CMU-17-214/f23-lab10. Run the following commands to get started: 37 | ``` 38 | mvn install 39 | mvn test 40 | ``` 41 | You might notice the tests are taking a very long time to run. Let's increase their performance using test doubles! Look through the provided files to see which methods you will need to test with which types of test doubles. You will find hints on how to proceed there. 42 | 43 | All of your tests should be written in `AndrewWebServicesTest.java`. You will also need to implement a fake database in `InMemoryDatabase.java`. For mocks, we will use the [Mockito](https://site.mockito.org/) framework. 44 | 45 | ## Mockito 46 | 47 | We will be using the mocking framework [Mockito](https://site.mockito.org/) in this lab. Here is a simple example to get you familiar with the important parts of Mockito. 48 | 49 | We'll use the `Cartoons` class for this example. The `Cartoons` class represents a mapping from characters to the cartoons they belong to. 50 | ``` 51 | public class Cartoons { 52 | private Map charactersToCartoons; 53 | 54 | public String get(String character) { 55 | return charactersToCartoons.get(character); 56 | } 57 | } 58 | ``` 59 | We use the `mock` method to create a mock of `Cartoons`: 60 | ``` 61 | Cartoons ourMock = mock(Cartoons.class); 62 | ``` 63 | 64 | Now we can use the `when` and `thenReturn` methods to add behavior to our mocked class (aka stub a method call): 65 | 66 | ``` 67 | when(ourMock.get("Snoopy")).thenReturn("Peanuts"); 68 | ``` 69 | 70 | So, we've specified that whenever we call `get("Snoopy")`, our mocked class should return "Peanuts". 71 | 72 | Next, we execute a method call on our mock: 73 | ``` 74 | String snoopyCartoon = ourMock.get("Snoopy"); 75 | ``` 76 | 77 | Now we use the `verify` method to check that our method was called with the given arguments. The following lines confirm that we invoked the `get` method on the mock and that the method returned a value that matches the expectation we set before: 78 | ``` 79 | verify(ourMock).get("Snoopy"); 80 | assertEquals(snoopyCartoon, "Peanuts") 81 | ``` 82 | 83 | So, now we've successfully mocked the `Cartoons` class and used a stub method call to write a test for the `get` method in `Cartoons`. 84 | 85 | This example covered everything you need to know for mocks in this lab. Feel free to checkout the [Mockito website](https://site.mockito.org/) for more information and documentation on the methods we used above, or look online for other examples using Mockito if the one above wasn't clear. Also, ask your TAs or ask on Piazza if you need any further help. Good luck! -------------------------------------------------------------------------------- /labs/lab07.md: -------------------------------------------------------------------------------- 1 | # Lab 7 - Test Double 2 | 3 | This lab is an introduction to test doubles. 4 | 5 | ## Deliverables 6 | - [ ] Use a fake to test `logIn` 7 | - [ ] Use stubs to test `getRecommendation` 8 | - [ ] Use mocks to test `sendPromoEmail` 9 | 10 | ## Introduction 11 | 12 | In testing, it may sometimes be necessary to use objects or procedures that look and behave like their release-intended counterparts but are actually simplified versions that reduce the complexity and facilitate testing. Objects or procedures meant for production can be too slow, unavailable, expensive, opaque, or non-deterministic. Instead, test doubles are often used. There are multiple types of test doubles, but the most well-known/popular are Fakes, Stubs, and Mocks. 13 | 14 | ### Fakes 15 | 16 | Fakes are fully functional classes with a simplified implementation. Usually, they take some shortcuts and are a simplified version of the real object. We use fakes to avoid interacting directly with objects that are too costly to access during testing, like databases. So, instead of querying our actual database, we use a fully functional in-memory database to simulate the same operations. 17 | 18 | 19 | 20 | ### Stubs 21 | 22 | A stub is an artificial class that returns pre-configured data. We use it to answer calls during tests. Stubs are used when we can't or don’t want to involve objects that would answer with real data or would have undesirable side effects. For example, instead of querying our real database, we may use a stub with predefined data to simulate only the functionality we need. 23 | 24 | 25 | 26 | ### Mocks 27 | 28 | A mock is an instrumented variant of a real class with fine-grained control. We use mocks when we don’t want to invoke expensive production code or when there is no easy way to verify that an intended action was executed. For example, we don't want to send a new email every time we want to test an email system. 29 | 30 | 31 | 32 | These three terms are usually used interchangeably in practice, but there are some subtle differences. You can find plenty of resources online that go into more detail on the differences if you're still unsure what they are (don't worry, even experienced software developers get it [wrong](https://martinfowler.com/articles/mocksArentStubs.html)). 33 | 34 | ## Instructions 35 | 36 | Clone the repository from [https://github.com/CMU-17-214/f24-lab07](https://github.com/CMU-17-214/f24-lab07). Run the following commands to get started: 37 | ``` 38 | mvn install 39 | mvn test 40 | ``` 41 | You might notice the tests are taking a very long time to run. Let's increase their performance using test doubles! Look through the provided files to see which methods you will need to test with which types of test doubles. You will find hints on how to proceed there. 42 | 43 | All of your tests should be written in `AndrewWebServicesTest.java`. You will also need to implement a fake database in `InMemoryDatabase.java`. For mocks, we will use the [Mockito](https://site.mockito.org/) framework. 44 | 45 | ## Mockito 46 | 47 | We will be using the mocking framework [Mockito](https://site.mockito.org/) in this lab. Here is a simple example to get you familiar with the important parts of Mockito. 48 | 49 | We'll use the `Cartoons` class for this example. The `Cartoons` class represents a mapping from characters to the cartoons they belong to. 50 | ``` 51 | public class Cartoons { 52 | private Map charactersToCartoons; 53 | 54 | public String get(String character) { 55 | return charactersToCartoons.get(character); 56 | } 57 | } 58 | ``` 59 | We use the `mock` method to create a mock of `Cartoons`: 60 | ``` 61 | Cartoons ourMock = mock(Cartoons.class); 62 | ``` 63 | 64 | Now we can use the `when` and `thenReturn` methods to add behavior to our mocked class (aka stub a method call): 65 | 66 | ``` 67 | when(ourMock.get("Snoopy")).thenReturn("Peanuts"); 68 | ``` 69 | 70 | So, we've specified that whenever we call `get("Snoopy")`, our mocked class should return "Peanuts". 71 | 72 | Next, we execute a method call on our mock: 73 | ``` 74 | String snoopyCartoon = ourMock.get("Snoopy"); 75 | ``` 76 | 77 | Now we use the `verify` method to check that our method was called with the given arguments. The following lines confirm that we invoked the `get` method on the mock and that the method returned a value that matches the expectation we set before: 78 | ``` 79 | verify(ourMock).get("Snoopy"); 80 | assertEquals(snoopyCartoon, "Peanuts") 81 | ``` 82 | 83 | So, now we've successfully mocked the `Cartoons` class and used a stub method call to write a test for the `get` method in `Cartoons`. 84 | 85 | This example covered everything you need to know for mocks in this lab. Feel free to checkout the [Mockito website](https://site.mockito.org/) for more information and documentation on the methods we used above, or look online for other examples using Mockito if the one above wasn't clear. Also, ask your TAs or ask on Piazza if you need any further help. Good luck! 86 | -------------------------------------------------------------------------------- /previous-labs/lab12.md: -------------------------------------------------------------------------------- 1 | # Lab 12 - Test Double (Fakes, Mocks, & Stubs) 2 | 3 | This recitation is an introduction to test doubles. 4 | 5 | ## Deliverables 6 | - [ ] Use a fake to test `logIn` 7 | - [ ] Use stubs to test `getRecommendation` 8 | - [ ] Use mocks to test `sendPromoEmail` 9 | 10 | ## Introduction 11 | 12 | In testing, it may sometimes be necessary to use objects or procedures that look and behave like their release-intended counterparts but are actually simplified versions that reduce the complexity and facilitate testing. Objects or procedures meant for production can be too slow, unavailable, expensive, opaque, or non-deterministic. Instead, test doubles are often used. There are multiple types of test doubles, but the most well-known/popular are Fakes, Stubs, and Mocks. 13 | 14 | ### Fakes 15 | 16 | Fakes are fully functional classes with a simplified implementation. Usually, they take some shortcuts and are a simplified version of the real object. We use fakes to avoid interacting directly with objects that are too costly to access during testing, like databases. So, instead of querying our actual database, we use a fully functional in-memory database to simulate the same operations. 17 | 18 | 19 | 20 | ### Stubs 21 | 22 | A stub is an artificial class that returns pre-configured data. We use it to answer calls during tests. Stubs are used when we can't or don’t want to involve objects that would answer with real data or would have undesirable side effects. For example, instead of querying our real database, we may use a stub with predefined data to simulate only the functionality we need. 23 | 24 | 25 | 26 | ### Mocks 27 | 28 | A mock is an instrumented variant of a real class with fine-grained control. We use mocks when we don’t want to invoke expensive production code or when there is no easy way to verify that an intended action was executed. For example, we don't want to send a new email every time we want to test an email system. 29 | 30 | 31 | 32 | These three terms are usually used interchangeably in practice, but there are some subtle differences. You can find plenty of resources online that go into more detail on the differences if you're still unsure what they are (don't worry, even experienced software developers get it [wrong](https://martinfowler.com/articles/mocksArentStubs.html)). 33 | 34 | ## Instructions 35 | 36 | Clone the AndrewWS repository from [https://github.com/CMU-17-214/s24-lab12](https://github.com/CMU-17-214/s24-lab12). Run the following commands to get started: 37 | ``` 38 | mvn install 39 | mvn test 40 | ``` 41 | You might notice the tests are taking a very long time to run. Let's increase their performance using test doubles! Look through the provided files to see which methods you will need to test with which types of test doubles. You will find hints on how to proceed there. 42 | 43 | All of your tests should be written in `AndrewWebServicesTest.java`. You will also need to implement a fake database in `InMemoryDatabase.java`. For mocks, we will use the [Mockito](https://site.mockito.org/) framework. 44 | 45 | ## Mockito 46 | 47 | We will be using the mocking framework [Mockito](https://site.mockito.org/) in this lab. Here is a simple example to get you familiar with the important parts of Mockito. 48 | 49 | We'll use the `Cartoons` class for this example. The `Cartoons` class represents a mapping from characters to the cartoons they belong to. 50 | ``` 51 | public class Cartoons { 52 | private Map charactersToCartoons; 53 | 54 | public String get(String character) { 55 | return charactersToCartoons.get(character); 56 | } 57 | } 58 | ``` 59 | We use the `mock` method to create a mock of `Cartoons`: 60 | ``` 61 | Cartoons ourMock = mock(Cartoons.class); 62 | ``` 63 | 64 | Now we can use the `when` and `thenReturn` methods to add behavior to our mocked class (aka stub a method call): 65 | 66 | ``` 67 | when(ourMock.get("Snoopy")).thenReturn("Peanuts"); 68 | ``` 69 | 70 | So, we've specified that whenever we call `get("Snoopy")`, our mocked class should return "Peanuts". 71 | 72 | Next, we execute a method call on our mock: 73 | ``` 74 | String snoopyCartoon = ourMock.get("Snoopy"); 75 | ``` 76 | 77 | Now we use the `verify` method to check that our method was called with the given arguments. The following lines confirm that we invoked the `get` method on the mock and that the method returned a value that matches the expectation we set before: 78 | ``` 79 | verify(ourMock).get("Snoopy"); 80 | assertEquals(snoopyCartoon, "Peanuts") 81 | ``` 82 | 83 | So, now we've successfully mocked the `Cartoons` class and used a stub method call to write a test for the `get` method in `Cartoons`. 84 | 85 | This example covered everything you need to know for mocks in this lab. Feel free to checkout the [Mockito website](https://site.mockito.org/) for more information and documentation on the methods we used above, or look online for other examples using Mockito if the one above wasn't clear. Also, ask your TAs or ask on Piazza if you need any further help. Good luck! 86 | -------------------------------------------------------------------------------- /labs/lab04.md: -------------------------------------------------------------------------------- 1 | # Lab 4: Software Design and UML 2 | 3 | During lecture, we discussed how we analyze problems, design solutions, and communicate them via UML diagrams. In this lab, you will practice creating UML diagrams for a hypothetical implementation of Blackjack. We encourage you to review the lecture notes, reference [UML and Patterns](https://cmu.primo.exlibrisgroup.com/discovery/fulldisplay?context=L&vid=01CMU_INST:01CMU&search_scope=MyInst_and_CI&tab=Everything&docid=alma991019576227704436) (Chapter 9-10, 14-15), and work with each other. You are free to draw the diagrams via paper and pencil, tablet, or whatever you choose as long as the diagrams are legible. We recommend [https://www.draw.io](https://www.draw.io). 4 | 5 | ## Deliverables 6 | 7 | - [ ] Create a domain model for Blackjack as described below, and develop a system sequence diagram depicting a single player starting a new game and playing one round of Blackjack. 8 | - [ ] Find and fix two problems with coupling/cohesion in the provided object model. 9 | - [ ] Create an object-level interaction diagram for a player choosing to hit in a round of Blackjack, consistent with your fixed object model and system sequence diagram. 10 | 11 | ## Instructions 12 | 13 | ### Background 14 | 15 | Suppose you are designing and implementing a simplified version of Blackjack, where up to 9 players plays against an automated dealer. 16 | Here is a short description of the game: 17 | 18 | The objective of Blackjack is to obtain a score higher than the dealer. In each round the **players** and the **dealer** are initially dealt 2 **cards**, with one of the dealer’s cards dealt face down. Each numerical card (2-9) is worth its **face value**, aces are worth either 1 or 11 (it is the player’s choice), and all face cards (ten, jack, queen, and king) are worth 10. 19 | 20 | At the beginning of each round each player must place a **_bet_**; this amount will not change for the rest of the round. After the bet, the first player repeatedly decides whether to **hit** (be dealt a new card, up to 5 cards in the player’s hand) or **stand** (stop being dealt cards). If the player **scores** more than 21 points, the player loses their bet. 21 | 22 | After the player stands, the next player takes their turn until all players have either stood or lost. Then, the dealer exposes their face-down card and must hit (be dealt cards) until the value of their cards is more than 16. If a _player’s score_ is more than the dealer’s final score (but less than or equal to 21) then the player wins an amount equal to their bet. A player also wins if they are dealt 5 cards worth 21 or fewer points. 23 | 24 | Otherwise, the player loses their bet. More information can be found on Wikipedia’s Blackjack page. 25 | 26 | ### Domain Model 27 | 28 | Build a vocabulary by creating a _domain model_ for this problem. Document all relevant concepts and include important attributes and associations. (Remember, a domain model is used to analyze the problem; it describes concepts and abstractions of the real world, not software classes.) 29 | 30 | ### System Sequence Diagram 31 | 32 | A _system sequence diagram_ is a model that shows, for one scenario of use, the sequence of events that occur between users(actors) and the system itself. 33 | 34 | A system sequence diagram should specify and show the following: 35 | 36 | 1. External actors 37 | 2. Messages (methods) invoked by these actors 38 | 3. Return values (if any) associated with previous messages 39 | 4. Indication of any loops or iteration area 40 | 41 | Create a _system sequence diagram_ to model the interactions of a single player starting a new game and playing one round of Blackjack. To start designing a solution, think about how the game flows from an initial action (e.g., a user clicking a button, or part of the system requesting some information) to the individual steps following that action. Carefully consider all the interactions a player can make with the system (e.g., the player takes a hit or the player makes a bet). Note, that a system sequence diagram **does not** include internals of how the system responds to user requests. 42 | 43 | ### Object Model 44 | 45 | Review the proposed object model for Blackjack: [https://drive.google.com/file/d/1XlAhszdys8pGbY4KSNXUnqZS9hw5LIm_/view?usp=sharing](https://drive.google.com/file/d/1XlAhszdys8pGbY4KSNXUnqZS9hw5LIm_/view?usp=sharing). 46 | ![lab04-object-model-problem](images/lab04/blackjack_object_problem.jpg) 47 | 48 | There are several poor design choices, involving low cohesion and high coupling. Find and correct two of these design problems on the object model. 49 | 50 | ### Interaction Diagram 51 | 52 | To start designing a solution, consider the scenario of: 53 | 54 | - During the game, a player decides to take the ‘hit’ action, which includes dealing an additional card, checking whether the player’s turn is over, etc. 55 | 56 | Create an _interaction diagram_ (using a UML sequence diagram) that models the **interaction among objects** in this scenario. Your diagram should include specific classes and methods in your **object model**. As you map out the interactions, consider how they might look different had you made different design decisions. Note: To help distinguish this artifact from system sequence diagrams, we sometimes call this an **object-level interaction diagram**. 57 | -------------------------------------------------------------------------------- /labs/git-basics.md: -------------------------------------------------------------------------------- 1 | # Git -- The Basics 2 | 3 | For all labs and homeworks, you are required to submit your work by pushing changes to your repositories. Throughout the semester you will learn to work with *git* and to use best practices. 4 | 5 | Git is a version control system, which is a fancy way to say that you can take *named* snapshots (i.e. make saves) of your code base with it throughout development, and you can easily revert back to any such saves should something go wrong. Sooner or later you will write code that breaks, and you’d wish to “undo” what you wrote. Without git, you’ll have to figure out what you changed and revert them manually, which is time-costly and error-prone. With git, if you made a save when your code was working, you can revert back to that in one command. You also document your work incrementally for others. 6 | 7 | ## First Steps: Submitting Work 8 | 9 | Let's start with the basics on the command line: 10 | 11 | ````bash 12 | git add 13 | git commit -m "" 14 | git push 15 | ```` 16 | 17 | **git add** adds files to the staging area, **git commit** saves everything on the staging area along with the given commit message, and **git push** records local commits to the remote repository. After pushing changes you should see them on GitHub. 18 | 19 | **Beyond the command line.** You can also push changes to your repository using the VSCode UI or use [GitHub Desktop](https://desktop.github.com/). In VSCode, the source control tab (3rd from the top) provides you with an interface where you can stage, commit, and push changes. Clicking the + icon on the file stages it to be committed. Once you have staged all of your files, you can use the text box to add a commit message and press commit. You can then use the UI to push. 20 | 21 | ## Important Git Concepts 22 | 23 | * **Git Repository:** A git repository is a database of files and their history. On a local computer it will be stored in a .git directory. A repository on your computer is called a *local repository*, and a (typically shared) repository stored somewhere online (e.g. on GitHub) is called a *remote repository*. 24 | * **Git Commit:** A git commit is a snapshot / save of your git repository. You make a save of your code base by making a git commit. A commit has an ID and a description. It follows another commit. You can later revert back to it. 25 | * **Working directory:** Code from a git repository can be *checked out* in a directory. This will copy all files from the (typically last) commit from the git database to your directory where you can edit them. 26 | * **Staging Area:** Before you can make a git commit, you need to specify the files you want to include in your commit. In git you do this by *adding* them to the staging area, where you can double check that you are saving what you want. The *commit* command will create a commit of all files staged, but not of other changed files in your working directory. 27 | * **Remote Repository:** A remote repository is like a folder on Google Drive. Just like how you could backup your local files online to Google Drive, you can backup your local Git Repository online as a remote repository. This also enables collaboration: remote repositories are usually shared, when your collaborators *push* (upload) new changes to a shared remote repository, you can *fetch* (download) them to your computer. 28 | * **Branching:** Git branching allows you to create new development paths for your code. Each path is called a branch. Changes on one branch are independent from changes made on a different branch. Later, if desired, changes from different branches can be merged together. People commonly use branching when implementing new features. They create a new “development branch” and implement new code on it, keeping the default “master branch” clean. If the new code works out, they merge changes from the development branch into the master branch. If it doesn’t work out, they just discard the development branch. This ensures that the master branch always contains working code. 29 | 30 | ![img](https://lh4.googleusercontent.com/dGUCNsOeIKcHSjAEj1XARjgulfXrbndajIB8KfpuJjLvOWFIcEH-Ts6R5bsvViIQf0YxUSBxXtURK0iEmaLh8Zy3BXWHLpgbAWFdpVfG_WAQ6INa3mI_pyzpve0GZLN5FpfK7lPJ0X-ps8ckeqF9JQ) 31 | 32 | ## Useful Git commands 33 | 34 | * `git clone ` (Clone, i.e. download in entirety a git repository from a remote location and check it out in a local working directory) 35 | * `git pull` (Pull, i.e. download, any new changes from the remote repository not previously downloaded and merge them into your local working directory) 36 | * `git add ...` (Add files to the staging area) 37 | * `git status` (Shows which files have been changed and which files are on the staging area) 38 | * `git commit -m ""` (Make a commit saving everything on the staging area. The save is tagged with a message ) 39 | * `git log` (List all the commits you’ve made) 40 | * `git push` (Push, i.e. upload, any new commits you made locally to the remote repository) 41 | * `git branch ""` (Create a new branch named ) 42 | * `git checkout ` (Check out files from the git repository to your local working directory of the branch named ) 43 | 44 | ## Good Git Practices 45 | 46 | Good practices help you and other engineers understand your development process. Especially: 47 | 48 | * Make clean, single purpose commits. 49 | * Leave meaningful but concise commit messages. 50 | * Commit early, commit often 51 | * Don’t alter published history 52 | * Don’t commit generated files 53 | 54 | ## Useful resources to learn git 55 | 56 | * [Git cheatsheet](https://education.github.com/git-cheat-sheet-education.pdf) -- A concise guide for git commands 57 | * [Pro Git book](https://git-scm.com/book/en/v2) -- expert guide to Git written by GitHub founder 58 | * [Git Game](https://learngitbranching.js.org/?locale=en_US) -- interactive tutorial and playground for practicing branching and merging 59 | -------------------------------------------------------------------------------- /previous-labs/git-basics.md: -------------------------------------------------------------------------------- 1 | # Git -- The Basics 2 | 3 | For all labs and homeworks, you are required to submit your work by pushing changes to your repositories. Throughout the semester you will learn to work with *git* and to use best practices. 4 | 5 | Git is a version control system, which is a fancy way to say that you can take *named* snapshots (i.e. make saves) of your code base with it throughout development, and you can easily revert back to any such saves should something go wrong. Sooner or later you will write code that breaks, and you’d wish to “undo” what you wrote. Without git, you’ll have to figure out what you changed and revert them manually, which is time-costly and error-prone. With git, if you made a save when your code was working, you can revert back to that in one command. You also document your work incrementally for others. 6 | 7 | ## First Steps: Submitting Work 8 | 9 | Let's start with the basics on the command line: 10 | 11 | ````bash 12 | git add 13 | git commit -m "" 14 | git push 15 | ```` 16 | 17 | **git add** adds files to the staging area, **git commit** saves everything on the staging area along with the given commit message, and **git push** records local commits to the remote repository. After pushing changes you should see them on GitHub. 18 | 19 | 20 | 21 | **Beyond the command line.** You can also push changes to your repository using the VSCode UI or use [GitHub Desktop](https://desktop.github.com/). In VSCode, the source control tab (3rd from the top) provides you with an interface where you can stage, commit, and push changes. Clicking the + icon on the file stages it to be committed. Once you have staged all of your files, you can use the text box to add a commit message and press commit. You can then use the UI to push. 22 | 23 | 24 | 25 | ## Important Git Concepts 26 | 27 | - **Git Repository:** A git repository is a database of files and their history. On a local computer it will be stored in a .git directory. A repository on your computer is called a *local repository*, and a (typically shared) repository stored somewhere online (e.g. on GitHub) is called a *remote repository*. 28 | - **Git Commit:** A git commit is a snapshot / save of your git repository. You make a save of your code base by making a git commit. A commit has an ID and a description. It follows another commit. You can later revert back to it. 29 | - **Working directory:** Code from a git repository can be *checked out* in a directory. This will copy all files from the (typically last) commit from the git database to your directory where you can edit them. 30 | - **Staging Area:** Before you can make a git commit, you need to specify the files you want to include in your commit. In git you do this by *adding* them to the staging area, where you can double check that you are saving what you want. The *commit* command will create a commit of all files staged, but not of other changed files in your working directory. 31 | - **Remote Repository:** A remote repository is like a folder on Google Drive. Just like how you could backup your local files online to Google Drive, you can backup your local Git Repository online as a remote repository. This also enables collaboration: remote repositories are usually shared, when your collaborators *push* (upload) new changes to a shared remote repository, you can *fetch* (download) them to your computer. 32 | - **Branching:** Git branching allows you to create new development paths for your code. Each path is called a branch. Changes on one branch are independent from changes made on a different branch. Later, if desired, changes from different branches can be merged together. People commonly use branching when implementing new features. They create a new “development branch” and implement new code on it, keeping the default “master branch” clean. If the new code works out, they merge changes from the development branch into the master branch. If it doesn’t work out, they just discard the development branch. This ensures that the master branch always contains working code. 33 | 34 | 35 | 36 | ![img](https://lh4.googleusercontent.com/dGUCNsOeIKcHSjAEj1XARjgulfXrbndajIB8KfpuJjLvOWFIcEH-Ts6R5bsvViIQf0YxUSBxXtURK0iEmaLh8Zy3BXWHLpgbAWFdpVfG_WAQ6INa3mI_pyzpve0GZLN5FpfK7lPJ0X-ps8ckeqF9JQ) 37 | 38 | ## Useful Git commands 39 | 40 | - `git clone ` (Clone, i.e. download in entirety a git repository from a remote location and check it out in a local working directory) 41 | - `git pull` (Pull, i.e. download, any new changes from the remote repository not previously downloaded and merge them into your local working directory) 42 | - `git add ...` (Add files to the staging area) 43 | - `git status` (Shows which files have been changed and which files are on the staging area) 44 | - `git commit -m ""` (Make a commit saving everything on the staging area. The save is tagged with a message ) 45 | - `git log` (List all the commits you’ve made) 46 | - `git push` (Push, i.e. upload, any new commits you made locally to the remote repository) 47 | - `git branch ""` (Create a new branch named ) 48 | - `git checkout ` (Check out files from the git repository to your local working directory of the branch named ) 49 | 50 | ## Good Git Practices 51 | 52 | Good practices help you and other engineers understand your development process. Especially: 53 | 54 | - Make clean, single purpose commits. 55 | - Leave meaningful but concise commit messages. 56 | - Commit early, commit often 57 | - Don’t alter published history 58 | - Don’t commit generated files 59 | 60 | ## Useful resources to learn git 61 | 62 | - [Git cheatsheet](https://education.github.com/git-cheat-sheet-education.pdf) -- A concise guide for git commands 63 | - [Pro Git book](https://git-scm.com/book/en/v2) -- expert guide to Git written by GitHub founder 64 | - [Git Game](https://learngitbranching.js.org/?locale=en_US) -- interactive tutorial and playground for practicing branching and merging 65 | 66 | -------------------------------------------------------------------------------- /previous-labs/lab07.md: -------------------------------------------------------------------------------- 1 | # Lab 7: Intro to TypeScript 2 | 3 | In this lab, you will be setting up Typescript environment, and reimplement the TypeScript version of recentmistakesfirst from your homework 1. 4 | 5 | ## Deliverables 6 | 7 | - [ ] Install and run TypeScript and dependencies. 8 | - [ ] Implement the "recent mistakes first" organizer successfully. 9 | - [ ] Pass the style check on TypeScript. `ts-standard` should report no violations. 10 | 11 | ## Setting Up Your Repo 12 | 13 | We will work with a version of the homework 1 repository modified to use TypeScript. Locally clone the following repository: [Lab 7](https://github.com/CMU-17-214/template-s24-lab07.git). 14 | 15 | ## TypeScript Installation Guide 16 | 17 | To run JavaScript applications outside the browser we will use Node.js. We will do this by writing TypeScript code and compiling it into JavaScript. 18 | 19 | ### Installing Node.js, npm, and TypeScript 20 | 21 | Follow these [instructions](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) to install Node.js on your system. We recommend you install it through [`nvm`](https://github.com/nvm-sh/nvm). If you’re working on a Windows machine, we recommend using [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) for installing `nvm` (and subsequently using WSL for all development in this class). 22 | 23 | The following command will automatically download the installation script and update your environment to install it: `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash` Verify it installed correctly by running: 24 | 25 | `command -v nvm`, which should output `nvm`. 26 | 27 | With `nvm` installed, you can then install Node.js. Run the command `nvm install node` which should install the latest version of Node. Then, run `nvm install-latest-npm` which should install the latest version of `npm` supported by the Node version you installed. 28 | 29 | **Package management with `npm`.** `npm` stands for the "Node package manager", we will use it for package management: 30 | 31 | - The `package.json` file is the configuration file, which lists dependencies and commands 32 | - `npm install` installs all dependencies and puts them in a local directory `node_modules`, which should *not* be committed to version control and is automatically in the search path for imports from JS/TS code 33 | - The `package.json` file has a `dev-dependencies` section, which are development tools not needed at runtime, such as test execution, compilers, and style checkers. 34 | - `npm install -g X` installs package X globally, so not just for the current directory. This is often useful for tools like TypeScript that are installed through `npm`. `npx` is a useful tool for executing a tool installed locally and hence not otherwise in the path, like `npx tsc`. 35 | - The `package.json` file has a `scripts` section, which is just a way to describe command line instructions that can be easily run with `npm run X` from the command line. These are just convenient shorthands. 36 | 37 | *Checkpoint:* Run `npm install` to install dependencies and tools locally. You can find them in the `node_modules` folder if you are interested. 38 | 39 | **Installing TypeScript.** To install TypeScript run `npm install -g typescript` and afterward `tsc` should be available on your command line. (The project we provide already sets up TypeScript, so `npm install` should already install TypeScript locally). 40 | 41 | *Checkpoint:* Confirm that `tsc --version` works in your working directory (or `npx tsc --version` if you installed it only locally). 42 | 43 | Run `tsc` to compile the TypeScript code. You can find the output in the `dist` directory. 44 | 45 | ### VSCode for TypeScript 46 | 47 | VSCode works for TypeScript out of the box, and no further set up needed. You should already have set up VScode for Java, but just in case, you can install VSCode following the [instructions](https://code.visualstudio.com/) on its homepage or using your operating system's package manager. 48 | 49 | **Running a Program in VSCode.** VSCode executes code in the debugger by default. Select “Start debugging” from the menu and confirm to use Node.js as the runtime. Note that the program will fail because the debugger does not support command line input, but everything until this part will execute. 50 | 51 | If you just want to run the code use a terminal or the built-in terminal in VSCode (“New Terminal”) and run `node dist/index.js` to start the compiled program (or `npm run start` for the preconfigured run script in `package.json`) 52 | 53 | ### Style checking with ts-standard 54 | 55 | Linters check your code against a style-guide that specifies some good coding conventions (and sometimes annoying nitpicky things). Linters automate the process of checking for common style flaws such as the use of magic numbers. We preconfigured the project with the (very picky) style checker *`ts-standard`*. It comes preconfigured in the project with `npm run lint` or just run it with `npx ts-standard` (or just `ts-standard` if you installed the package globally). It has a fix option `npx ts-standard --fix` that will automatically fix many issues, which can be very useful. To integrate `ts-standard` into VSCode, install the *StandardJS* extension and in the settings pick `ts-standard` as the engine. 56 | 57 | ## Typescript Flash Card 58 | 59 | ### Compiling and running recap 60 | 61 | The flash card project is setup with `npm` already. `npm install` will install packages, `npm run compile` will run the TypeScript compiler, and `npm run start` will start the compiled program. *Tip*: When using `npm run start`, type `--` after start to ensure arguments you pass are interpreted as part of the `flashcard` command, that is `npm run start -- `. 62 | 63 | The project comes preconfigured with [ts-standard](https://github.com/standard/ts-standard), which you can execute with `npm run lint` or `npx ts-standard`. It is very opinionated and picky about style and will fail the build on minor deviations. You can let it auto-format many things with `npx ts-standard --fix`. 64 | 65 | ## Testing 66 | 67 | The project also comes confiured with [jest](https://jestjs.io/), which you can run with `npm run test`. The tests are located in the `tests` directory at the top-level. When you first run `jest`, one test should pass, and one test should fail. The failing test should pass when you implement the `recentMistakesFirst` functionality. 68 | 69 | ## Blocking I/O 70 | 71 | The code uses blocking I/O calls for simplicity, which are not idomatic in Node.js. We will discuss better solutions later in the class. 72 | -------------------------------------------------------------------------------- /labs/lab05.md: -------------------------------------------------------------------------------- 1 | # Lab 5: Refactoring and Anti-Patterns 2 | 3 | ## Introduction 4 | A lot of the design principles and heuristics we have discussed in this class are there to encourage good design *up-front*. But you do not always have control over how a system you are using gets created. 5 | 6 | 7 | **Anti-patterns** are common examples of bad design. They tend to come about due to a program’s natural evolution, coupled with poor choices early on, which leads to code that is increasingly *tangled*, badly coupled, low on cohesion, etc. These are often signaled by **code smells** -- heuristic, but not guaranteed indicators of anti-patterns, like overly long methods, or a class that calls a lot of another class’ code (feature envy, signals high coupling). 8 | 9 | In this lab, you will become a refactoring agent who detects anti-patterns and poor design decisions within the code, and attempts to fix them. 10 | ## Deliverables 11 | 12 | - [ ] Identify one design problem with Frogger crossing the road (in Frogger.java and Road.java). Explain the design problem to the TA and show an improved implementation that fixes the design problem. 13 | - [ ] Identify one design problem with Frogger recording themselves (in Frogger.java and Records.java). Explain the design problem to the TA and show an improved implementation that fixes the design problem. 14 | - [ ] Identify at least two issues (no need to name the anti-pattern) associated with the Drawing System, and explain how you would refactor it to the TA. No coding required. 15 | 16 | ## Instructions 17 | 18 | ### Setup 19 | Fork and clone the repo from [https://github.com/CMU-17-214/f24-lab05](https://github.com/CMU-17-214/f24-lab05). 20 | The task is provided in Java. If you would like some additional exercise, feel free to look into the "accounts" folder and identify the anti-pattern associated with it. 21 | 22 | In the appendix, we have provided a non-comprehensive list of anti-patterns. You might want to read and refer to when doing the tasks. 23 | 24 | ### Task 1 25 | Frogger is trying to cross the road, which she holds as a "Road" object in her fields. The Road object holds a boolean array indicating which steps are “occupied”; Frogger is on a specific square (“position”) and provides a move method (either forward or backward). 26 | 27 | In the frogger folder, navigate to the Frogger.java and Road.java classes and take a look at the code. What is it doing and which anti-pattern is present? Try to fix the design by modifying the two classes. 28 | 29 | > Hint: 30 | > + What information should Frogger hold? Does it do things that appear unusual for a Frogger? 31 | 32 | 33 | ### Task 2 34 | 35 | Frogger crossed the road and remembered: she was here to *record* her identity status at the Frogger Office. This is held in the "Records" object in her field. Frogger tries to fill in the fields according to the Record object. But there are simply too many things to fill in. 36 | 37 | Take a look at Records.java and then Frogger.java (again). What anti-pattern is present? Then try to fix the design by modifying the two classes. Alternatively, take a look at FroggerID.java. How might you use it? 38 | 39 | ### Task 3 40 | 41 | Next, let's study the “drawing” system. Open the drawing folder--and start by reading Drawing.java. There seem to be several design problems involved: think through them. For each of the poor design decisions below, think about how you would refactor them (no need to write actual code), and explain two of these refactorings to your TA. (The entire folder contains more design problems than the ones we've described below. If you would some additional practice, feel free to explore!) 42 | 43 | 1. The "draw" function seems to duplicate itself. How would you refactor it so that we don't need to rewrite the functionality everytime we introduce a new file type? 44 | 2. Take a look at ``` Drawing.java ```. Somewhere inside the "draw" function, the code seems to be explicitly creating an array of Lines and feeding it to the shape. How would you refactor it so that we don't need to expose and rely on such information inside our Drawing class? 45 | 46 | 47 | ## Appendix 48 | 49 | Below are a few anti-patterns/code smells, together with a brief explanation and possible refactoring actions. This list is not meant to be a comprehensive: it only includes several common examples. You don’t need to memorize this list. Instead, try to learn to recognize these patterns using the examples provided. You should also be able to discover new ones using the resources pointed to. 50 | 51 | 1. **Feature envy**: this antipattern happens when one class uses a lot of another’s functionality. This strongly indicates that some of the work being done in the former belongs in the latter (information expert). 52 | - Refactoring: move methods/fields, possibly part or some of them, to the information expert. This might work for inappropriate intimacy (below), but if both classes really need the same fields, create a delegate that can be used by both instead. 53 | - Related: **inappropriate intimacy**, where one class relies too much on the implementation details (fields, protected methods) of another. 54 | 55 | 2. **Large (“god”) class**: one class that has many responsibilities (poor cohesion). 56 | - Refactoring: extract classes to delegate to, sub-class if you need inheritance. It can also help to extract an interface, by identifying important components. 57 | - Related: **middle man**, where one class only exists to delegate work elsewhere. This smell applies to classes that don’t do any actual work, and can also show up in small classes. 58 | 59 | 3. **Message chains**: one method makes a series of calls on the return values of another. Think of the CardDeck → FlashCard.getStatus() → CardStatus.getSuccesses example. 60 | - Refactoring: create a delegate method in the intermediate class (e.g. ‘getSuccesses’ on ‘FlashCard’). 61 | 62 | 4. **Shotgun Surgery**: making any change requires changing a lot of code (bad responsibility assignment). 63 | 64 | 5. **Long method**: a method does too many things at once. 65 | - Refactoring: extract any cohesive parts to separate methods. 66 | 67 | 6. **Long parameter list**: a long list of parameters provided to a method. 68 | - Refactoring: identify an object that already holds all or most of these parameters, or create a “parameter Object” to pass instead. If this does not apply, identify if any parameters require a method call to compute on the caller’s side and move that method call into the method. 69 | 70 | 7. **Refused bequest**: two classes are connected through inheritance despite rather limited similarities (excessive coupling). 71 | - Refactoring: either restructure the hierarchy to a much simpler superclass object (if inheritance is really appropriate), or (more commonly) extract a delegate for the shared functionality. 72 | 73 | 8. **Excessive Instanceof**: a function uses multiple "instanceOf" calls to determine the type of the object it is interacting with. This is bad encapsulation and hard to extend. 74 | - Refactoring: restructure the code by invoking a more general class or interface that the subclasses may program against. 75 | -------------------------------------------------------------------------------- /previous-labs/lab06.md: -------------------------------------------------------------------------------- 1 | # Lab 6: Refactoring and Anti-Patterns 2 | 3 | ## Introduction 4 | A lot of the design principles and heuristics we have discussed in this class are there to encourage good design *up-front*. But you do not always have control over how a system you are using gets created. 5 | 6 | 7 | **Anti-patterns** are common examples of bad design. They tend to come about due to a program’s natural evolution, coupled with poor choices early on, which leads to code that is increasingly *tangled*, badly coupled, low on cohesion, etc. These are often signaled by **code smells** -- heuristic, but not guaranteed indicators of anti-patterns, like overly long methods, or a class that calls a lot of another class’ code (feature envy, signals high coupling). 8 | 9 | In this lab, you will become a refactoring agent who detect anti-patterns and poor design decisions within the code, and attempt to fix them. 10 | ## Deliverables 11 | 12 | - [ ] Identify one design problem with Frogger crossing the road (in Frogger.java and Road.java). Explain the design problem to the TA and show an improved implementation that fixes the design problem. 13 | - [ ] Identify one design problem with Frogger recording themselves (in Frogger.java and Records.java). Explain the design problem to the TA and show an improved implementation that fixes the design problem. 14 | - [ ] Identify at least two issues (no need to name the anti-pattern) associated with the Drawing System, and explain how you would refactor it to the TA. No coding required. 15 | 16 | ## Instructions 17 | 18 | ### Setup 19 | Fork and clone the repo from [https://github.com/CMU-17-214/s24-lab06](https://github.com/CMU-17-214/s24-lab06.git). 20 | The task is provided in Java. If you would like additional exercise, feel free to look into the "accounts" folder and identify the anti-pattern associated with it. 21 | 22 | In the appendix, we have provided a non-comprehensive list of anti-patterns you might want to read and refer to when doing the tasks. 23 | 24 | ### Task 1 25 | Frogger is trying to cross the road, which she holds as a "Road" object in her fields. The latter holds a boolean array indicating which steps are “occupied”; Frogger is on a specific square (“position”) and provides a move method (either forward or backward). 26 | 27 | In the frogger folder, navigate to the Frogger.java and Road.java classes and take a look at the code. What is it doing and what anti-pattern is present? Then try to fix the design by modifying the two classes. 28 | 29 | > Hint: 30 | > + What information should the Frogger hold? Does it do things that appear weird for a Frogger? 31 | 32 | 33 | ### Task 2 34 | 35 | Frogger crossed the road and remembered: she was here to *record* her identity status at the Frogger Office. That's why there is a "Records" object in her field. Frogger tries to fill in the fields according to the Record object. But there is simply too many things to fill in--Frogger is annoyed. 36 | 37 | Take a look at Records.java and then Frogger.java (again). What anti-pattern is present? Then try to fix the design by modifying the two classes... or, take a look at FroggerID.java. How might you use it for convenience? 38 | 39 | ### Task 3 40 | 41 | Next, let's study the “drawing” system. Open the drawing folder--you may want to start by reading Drawing.java. There seems to be several design problems involved, and let's think through them. For each of the poor design decisions below, think about how you would refactor them (no need to write actual code), and explain 2 of these refactorings to your TA. (The entire folder contains more design problems than the ones we've described below. If you would like additional exercise, feel free to explore!) 42 | 43 | 1. The "draw" function seems to duplicate itself. How would you refactor it so that we don't need to rewrite the functionality everytime we introduce a new file type? 44 | 2. Somewhere inside the "draw function", the code seems to be explicitly creating an array of Lines and feeding it to the shape. How would you refactor it so that we don't need to expose and rely on such information inside our Drawing class? 45 | 46 | 47 | ## Appendix 48 | 49 | Below are a few of the many anti-patterns/code smells that people have identified, with a brief explanation and refactoring actions. This is not meant to be a comprehensive list; it includes several common examples. And you don’t need to memorize all of it; instead, try to learn to recognize them through examples like the ones below, and occasionally discover new ones using the resources we pointed to. 50 | 51 | 1. **Feature envy**: when one class uses a lot of another’s functionality. This strongly indicates that some of the work being done in the former belongs in the latter (information expert). 52 | - Refactoring: move methods/fields, possibly part or some of them, to the information expert. This might work for inappropriate intimacy (below), but if both classes really need the same fields, create a delegate, used by both instead. 53 | - Related: **inappropriate intimacy**, where one class relies too much on the implementation details (fields, protected methods) of another. 54 | 55 | 2. **Large (“god”) class**: one class that has many responsibilities (poor cohesion). 56 | - Refactoring: extract classes to delegate too, sub-class if you need inheritance. Also helps to extract an interface, to identify the important components. 57 | - Related: **middle man**, where one class only exists to delegate work elsewhere. But note that this smell applies to classes that don’t do any actual work, and can also show up in small classes. 58 | 59 | 3. **Message chains**: one method makes a series of calls on the return values of another. Think of the CardDeck → FlashCard.getStatus() → CardStatus.getSuccesses example from the midterm. 60 | - Refactoring: create a delegate method in the intermediate class (e.g. ‘getSuccesses’ on ‘FlashCard’). 61 | 62 | 4. **Shotgun Surgery**: making any change requires changing a lot of code (bad responsibility assignment). 63 | 64 | 5. **Long method**: a method does too many things at once. 65 | - Refactoring: extract any cohesive parts to separate methods. 66 | 67 | 6. **Long parameter list**: a long list of parameters provided to a method. 68 | - Refactoring: identify an object that already holds all/most of these parameters, or create a “parameter Object” if not; pass that instead. If this does not apply, identify if any parameters require a method call to compute on the caller’s side; move that method call into the method. 69 | 70 | 7. **Refused bequest**: two classes are connected through inheritance despite rather limited similarities (excessive coupling). 71 | - Refactoring: either restructure the hierarchy to a much simpler superclass object (if inheritance is really appropriate to the remainder), or (more commonly) extract a delegate for the shared functionality. 72 | 73 | 8. **Excessive Instance of**: a function uses multiple "instanceOf" calls to determine the type of the object it is interacting with. This is bad encapsulation and hard to extend. 74 | - Refactoring: restructure the code by invoking a more general class or interface that the subclasses may program against. 75 | -------------------------------------------------------------------------------- /.assets/style.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:0 0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0} 2 | 3 | body { 4 | font-family: 'Helvetica Neue', Helvetica, sans-serif; 5 | font-size: .9em; 6 | padding: 50px 0; 7 | } 8 | p, td, th { 9 | line-height: 1.3em; 10 | } 11 | a { 12 | color: #04668a; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #990000; 17 | text-decoration: underline; 18 | } 19 | li { 20 | margin: 5px 0; 21 | } 22 | hr { 23 | border: 0; 24 | height: 0; 25 | border-top: 5px #f5f5f5 solid; 26 | margin: 40px 0 30px; 27 | } 28 | #navigation { 29 | background: #f5f5f5; 30 | padding: 10px 0; 31 | width: 100%; 32 | position: fixed; 33 | top: 0; 34 | border-bottom: 1px #ddd solid; 35 | } 36 | #navigation ul { 37 | padding: 0; 38 | margin: 0; 39 | float: right; 40 | } 41 | #navigation li { 42 | margin: 0; 43 | margin-left: 20px; 44 | list-style: none; 45 | float: left; 46 | } 47 | #navigation .course-semester { float: left; } 48 | #navigation .course { 49 | text-transform: uppercase; 50 | font-weight: bold; 51 | display: inline-block; 52 | } 53 | #navigation .semester { 54 | font-size: .75em; 55 | display: inline-block; 56 | margin-left: 10px; 57 | } 58 | #hamburger { 59 | display: none; 60 | cursor: pointer; 61 | float: right; 62 | margin-top: -4px; 63 | width: 25px; 64 | outline: none; 65 | -webkit-tap-highlight-color: rgba(0,0,0,0); 66 | } 67 | #hamburger div { 68 | border: 2px solid #04668a; 69 | border-radius: 2px 2px 2px 2px; 70 | margin-top: 3px; 71 | } 72 | #hamburger:active div { 73 | border: 2px solid #990000; 74 | } 75 | 76 | header { 77 | padding: 20px 0; 78 | } 79 | h1 { 80 | margin-top: 35px; 81 | font-size: 1.6em; 82 | } 83 | h1 small { 84 | font-weight: normal; 85 | display: block; 86 | } 87 | 88 | section { padding: 35px 0 0; } 89 | section:last-child { border: 0; } 90 | 91 | .container { 92 | padding-left: 5%; 93 | padding-right: 5%; 94 | max-width: 960px; 95 | margin: 0 auto; 96 | } 97 | .cf:before, 98 | .cf:after, 99 | .container:before, 100 | .container:after { 101 | content: " "; 102 | display: table; 103 | } 104 | .cf:after, 105 | .container:after { 106 | clear: both; 107 | } 108 | .toad { 109 | display: inline-block; 110 | overflow: hidden; 111 | padding: 20px; 112 | margin-right: 20px; 113 | float: left; 114 | background: #fff; 115 | border-radius: 50%; 116 | border: 5px #f7f3ff solid; 117 | } 118 | .toad:hover { 119 | border: 5px #e3f2c7 solid; 120 | } 121 | .toad img { 122 | max-height: 75px; 123 | max-width: 75px; 124 | } 125 | 126 | table { 127 | width: 100%; 128 | } 129 | th { 130 | text-align: left; 131 | } 132 | th, 133 | td { 134 | vertical-align: top; 135 | padding: 10px 5px; 136 | } 137 | #schedule tr { 138 | border-bottom: 1px #ddd dotted; 139 | } 140 | 141 | #schedule table tbody:nth-child(2n+1) { background-color: #f5f5f5; } 142 | 143 | #office-hours table thead, 144 | #schedule table thead, 145 | #schedule table tbody:nth-child(2n+1), 146 | #schedule table tbody:nth-child(2n) { 147 | border-bottom: 3px #ccc solid; 148 | } 149 | #office-hours tbody tr:last-child, 150 | #schedule tbody tr:last-child { 151 | border: 0 !important; 152 | } 153 | #schedule .hw, 154 | #schedule .rec { 155 | padding: 0 5px; 156 | border-radius: 3px; 157 | text-transform: lowercase; 158 | } 159 | #schedule .hw { color: #fff; background: #04668a; } 160 | #schedule .rec { background: #f4cd38; } 161 | 162 | #office-hours td, 163 | #office-hours th { 164 | border: 1px #ccc solid; 165 | } 166 | #office-hours th { 167 | background: #f5f5f5; 168 | } 169 | #office-hours td div { 170 | border-top: 1px #eee solid; 171 | margin-top: 10px; 172 | padding-top: 10px; 173 | } 174 | #office-hours td div:first-child { 175 | margin: 0; 176 | padding: 0; 177 | border: 0; 178 | } 179 | .midterm, 180 | .final { 181 | font-weight: bold; 182 | color: #e76600; 183 | } 184 | .break { 185 | font-weight: bold; 186 | } 187 | 188 | .instructor { 189 | float: left; 190 | width: 250px; 191 | padding: 10px 0; 192 | } 193 | .section { 194 | font-weight: bold; 195 | width: 20px; 196 | display: inline-block; 197 | } 198 | .time { 199 | display: inline-block; 200 | width: 160px; 201 | } 202 | .location { 203 | display: inline-block; 204 | width: 80px; 205 | } 206 | h2{ margin-top: 4em; 207 | } 208 | 209 | @media (max-width: 600px) { 210 | body.push { 211 | padding-top: 194px; 212 | } 213 | .toad { 214 | display: block; 215 | padding: 10px; 216 | float: none; 217 | width: 50px; 218 | margin: 0 auto; 219 | } 220 | .toad img { 221 | max-height: 50px; 222 | max-width: 50px; 223 | } 224 | h1 { 225 | margin: 10px 0; 226 | text-align: center; 227 | font-size: 1.35em; 228 | line-height: 1.4em; 229 | } 230 | h2 { 231 | font-size: 1.2em; 232 | } 233 | h3 { 234 | font-size: 1em; 235 | } 236 | #hamburger { 237 | display: block; 238 | } 239 | #navigation ul { 240 | margin-top: 27px; 241 | margin-bottom: -10px; 242 | float: none; 243 | clear: both; 244 | } 245 | #navigation li { 246 | margin: 0 -5.5%; 247 | float: none; 248 | } 249 | #navigation li a { 250 | display: block; 251 | background: #eee; 252 | padding: 10px 5%; 253 | } 254 | #navigation li a:hover { 255 | text-decoration: none; 256 | background: #f5f5f5; 257 | } 258 | #navigation.hidden ul { 259 | display: none; 260 | } 261 | #schedule thead { 262 | display: none; 263 | } 264 | #schedule tr { 265 | display: block; 266 | padding: 10px 5px; 267 | } 268 | #schedule td { 269 | display: block; 270 | padding: 0 5px; 271 | } 272 | #schedule td:first-child { 273 | font-size: 0.75em; 274 | text-transform: uppercase; 275 | float: right; 276 | } 277 | #schedule td:nth-child(2) { 278 | margin-bottom: 10px; 279 | } 280 | #schedule td:nth-child(3), 281 | #schedule td:nth-child(4) { 282 | background: #f7f3ff; 283 | border: 1px #ddd solid; 284 | margin: 5px; 285 | margin-bottom: 0; 286 | font-size: 0.8em; 287 | padding: 5px; 288 | } 289 | #schedule td:empty { 290 | border: 0; 291 | padding: 0; 292 | margin: 0; 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /previous-labs/f23-lab12.md: -------------------------------------------------------------------------------- 1 | # Lab 12 - Cloud Deployment 2 | 3 | Repo link: [https://github.com/CMU-17-214/f23-rec12-fixed](https://github.com/CMU-17-214/f23-rec12-fixed) 4 | 5 | In this recitation, you will deploy a version of the TicTacToe game to the 6 | Google Cloud Compute Engine service, allowing you to access it remotely. You can use the same strategy if you want to release your Santorini implementation publicly. 7 | 8 | ## Deliverables 9 | - [ ] Enable the Google Cloud Compute Engine service, and create a virtual machine. 10 | - [ ] Successfully run a Docker image on your cloud virtual machine and show the running site to the TA. 11 | - [ ] Make a change to the code and update the image on the cloud. 12 | 13 | ## Introduction 14 | One of the services provided by Google (and Amazon, Microsoft, etc.) is the 15 | ability to use servers that they have as _virtual machines_. This allows you to 16 | skip a lot of the work needed to assemble your own server, connect it to the 17 | internet, and maintain hardware that might fail. It also allows you to quickly deploy web applications and observe changes as you make them. 18 | 19 | The instructions here are highly manual, and almost all of them can be automated. 20 | This is out of the scope of this course, but other CMU courses focused on DevOps or cloud computing (e.g., 17-346/646, 15-319/619) go into more depth on modern tooling to automate them. 21 | 22 | ## Instructions 23 | 24 | ### Fork the starter repository 25 | 26 | 1. Create your own fork of [the starter repository](https://github.com/CMU-17-214/f23-rec12-fixed). 27 | 28 | ### Setting up a new virtual machine 29 | We continue to use the Google Cloud Platform as in Lab 8 and HW5, for which we provided coupons to get free credits. NOTE: We do not have any additional backup coupons. If you have not yet resolved coupon issues, you will not be able to complete this portion of the lab or have to use another billing account. 30 | 31 | 32 | You may or may not have Google Cloud APIs enabled that you need for these 33 | steps. If you do not, choose "Enable" when prompted. 34 | 35 | 2. On the [Google Cloud Console](https://console.cloud.google.com), click the 36 | "Create a VM" button. 37 | 38 | ![createvm](images/lab12/create-a-vm.png) 39 | 40 | 3. Give your VM a name. 41 | 42 | 4. It is ok to use the default E2 machines, but under the "Machine type" 43 | dropdown select `e2-small` 44 | 45 | ![selectvm](images/lab12/select-vm.png) 46 | 47 | 5. Under "Firewall", select the boxes for "Allow HTTP traffic" and "Allow HTTPS 48 | traffic". 49 | 50 | ![selecttraffic](images/lab12/select-traffic.png) 51 | 52 | 6. Click "Create". 53 | 54 | 7. You will be brought to a screen with a list of VM instances, and should see 55 | your newly created VM, together with an "External IP" that you can use to 56 | connect to it (in this case it's 34.69.81.171). 57 | 58 | ![details](images/lab12/details.png) 59 | 60 | ### Connecting to your virtual machine 61 | Similar to lab 8 and homework 5, you will be using the Google Cloud CLI `gcloud` 62 | to run these commands. If you do not have it set up properly, please refer back 63 | to the lab 8 instructions. 64 | 65 | 8. On your local machine, run `gcloud init` to make sure you are logged in to 66 | the Google Cloud service. 67 | 68 | 9. Log in to your virtual machine with `gcloud compute ssh 69 | --project=[YOUR_PROJECT_NAME] [YOUR_VM_NAME]` 70 | 71 | 10. We will be using Docker to deploy this lab. Install the latest version of 72 | Docker on the remote machine using [the instructions 73 | here](https://docs.docker.com/engine/install/debian/#install-using-the-repository). 74 | 75 | ### Sign up for a Docker account and set up a new repository 76 | 77 | 11. Create a new account on [https://hub.docker.com](https://hub.docker.com). This will be used for 78 | creating Docker images and pushing them to Docker Hub for deployment to your new 79 | virtual machine. 80 | 81 | 12. Sign in to Docker Hub. Once you are signed in select "Create repository". For 82 | the name, select something reletavely memorable (e.g., "lab12"). We do not 83 | recommend creating a private repository, or you will have to sign in to your 84 | docker account on the virtual machine as well. 85 | 86 | ### Install Docker on your local computer 87 | 88 | For this lab, we will be compiling, containerizing, and deploying an app to 89 | Docker Hub locally so that they can be easily deployed to the cloud. Note: IF AT 90 | ANY TIME YOU RUN INTO ISSUES HERE, PLEASE JUMP TO THE [EMERGENCY BAILOUT 91 | INSTRUCTIONS](#emergency-bailout-instructions) below. These instructions are 92 | tested and use the virtual machine itself for compilation and containerization, 93 | which is a much less realistic use case, but should allow you to complete the lab. 94 | 95 | 13. Download the Docker Desktop installer from the [Docker Desktop 96 | website](https://docs.docker.com/desktop/), and follow the instructions to 97 | install it. 98 | 99 | 14. From Docker Desktop, sign in to your account using the credentials you 100 | created in the previous step. 101 | 102 | ### Build and deploy a Docker container 103 | 15. On your local machine, clone the repository you forked, and follow the instructions in its README.md to build a Docker image. 104 | 105 | 16. You should be able to see the Docker image you just created with `docker images`. 106 | 107 | 17. Now create a new Docker tag matching your Docker Hub repository name. To do this run 108 | `docker tag lab12 109 | [dockerhub-user-name]/[repository-name]`. `[dockerhub-user-name]/[repository-name]` 110 | should match your user name and the repository name you created on Docker Hub. 111 | 112 | 18. Check that the images you created exist with `docker images`. You should see 113 | two images under the `REPOSITORY` column corresponding to the two you just 114 | created. 115 | 116 | 19. Push the `[dockerhub-user-name]/[repository-name]` image to Docker Hub with 117 | `docker push [dockerhub-user-name]/[repository-name]`. 118 | 119 | 120 | ### Pull the image from Docker Hub on the Google Cloud VM 121 | 20. Log back into the Google Cloud VM you created earlier with the `gcloud compute ssh` command from step 9. 122 | 123 | 21. Download the image you just pushed to Docker Hub onto the VM using `docker pull 124 | [dockerhub-user-name]/[repository-name]`. Check that it exists using `docker 125 | images`. 126 | 127 | 24. Run the Docker image you just pulled with `docker run -p 80:8080 128 | [dockerhub-user-name]/[repository-name]`. The parameter `-p 80:8080` maps port 8080 of the virtual machine to port 80 of your local machine. You should see the message "Running on 129 | port 8080!" if it is successful and should be able to access the game locally on port 80 (i.e., just `http://`). 130 | 131 | 25. Navigate your web browser to the IP address of the container you created 132 | earlier (i.e., the IP from step 7). You should see the same TicTacToe interface from Lab 7. Skip to step 30 if you got to this point successfully. 133 | 134 | ### EMERGENCY BAILOUT INSTRUCTIONS 135 | 136 | If it turns out that you are having trouble setting up Docker locally, you do 137 | have a virtual Linux machine that you can use to build the Docker 138 | image. Although this is an unrealistic use case, you can get set up with a 139 | container following these instructions. 140 | 141 | 26. Log in to the VM you started on Google Cloud with the `gcloud compute ssh` command from step 9 above. Since you'll be compiling on 142 | the VM, you should first install the additional dependencies using `apt install 143 | maven openjdk-17-jdk nodejs npm`. 144 | 145 | 27. Clone your fork of the starter repository to the Google Cloud VM. Follow the instructions in its README.md to build a Docker image. You do not need to interact with Docker Hub with this method. 146 | 147 | 28. Run the Docker image you just created with `docker run -p 80:8080 lab12`. 148 | 149 | 29. Navigate your web browser to the IP address of the container you created earlier (i.e., the IP from step 7). You should see the same TicTacToe interface from Lab 7. 150 | 151 | ### Make a change to the code 152 | Before you make a change, you can use Ctrl-C to kill the running Docker image on your VM. 153 | 154 | 30. In the forked repository, edit the last line of `front-end/src/App.css` to make playable cells `blue` instead of `red`. 155 | *If you followed the Emergency Bailout Instructions above*, you should make this change on your local computer, commit it, and push it to GitHub. Then, from the Google Cloud VM you can do a `git pull` and the code will be updated. 156 | 157 | 31. From the machine you built the image on, re-build the front end by running `npm run compile` in the `front-end` directory. 158 | 159 | 32. Re-build the Docker image using `docker build -t lab12 --platform linux/amd64 .`. *If you followed the Emergency Bailout Instructions above, skip the next step. 160 | 161 | 33. Update the tag, push to Docker hub, and pull the new image from Docker hub following steps 17 through 21 above. 162 | 163 | 34. Re-run the docker image you just created on the VM using `docker run`. You should see the new website running when you point your web browser to the IP address of the container. 164 | 165 | --- 166 | 167 | Remember to shut down the virtual machine if you do not need it anymore to stop paying credits for it. 168 | -------------------------------------------------------------------------------- /labs/lab11.md: -------------------------------------------------------------------------------- 1 | # Lab 11: TicTacToe Client/Server 2 | 3 | ## Context 4 | TicTacToe is a two-player game where the players take turns marking the spaces in a three-by-three grid with either X or O. The first player to place three of their marks in a horizontal, vertical, or diagonal row is the winner. More information about the game can be found [here](https://en.wikipedia.org/wiki/Tic-tac-toe). In this recitation, you will work on an implementation of the TicTacToe game. 5 | 6 | This version of TicTacToe is meant to help you set up Homework 6a (User Interface for santorini). It uses a Java backend using a NanoHttpd server and a TS frontend using React.js. This client/server style architecture is commonly used in developing web applications. However, this is a very big topic, we will only cover the essentials for this lab and Homework 6. 7 | 8 | ## Deliverables 9 | - [ ] Extend the implementation to show the current player and winner of the game in the “instructions” panel of the game. 10 | - [ ] Extend the implementation of the game to allow users to undo steps. 11 | - [ ] Change the styling of the game with CSS files (e.g., change colors). 12 | 13 | ## Instructions 14 | Clone the TicTacToe repository from: https://github.com/CMU-17-214/f24-lab11 15 | 16 | Refer to the README’s of the projects therein for set up instructions. After you run the program, you will be able to play the game through the GUI as illustrated in the snippet below from the link http://localhost:3000/. 17 | 18 | ![tictactoe](images/lab11/tictactoe.png) 19 | 20 | 21 | Today’s recitation is all about learning to read and navigate this type of code. The deliverables require you to implement a few very simple improvements, that won’t take you much time at all once you get the hang of how the code is written and structured. So prioritize reading the code and thinking about the flow of information and control. 22 | 23 | Instructions: Right now, the game doesn’t tell the user much; once someone has won, it just stops responding. Let’s add an “instructions” element to the HTML body, with the ID “instructions”. The CSS for this element is already present. The text in this element should indicate whose turn it is, or who has won the game (if applicable). Hint: think about all the places affected by this, in terms of client/view (HTML), and server/controller. How do other elements get updated? 24 | 25 | Undo: The “Undo” button currently does nothing at all. Let’s wire it up. Much like in the previous exercise, think about all the places where changes need to be made. This one will also require you to get into the game implementation (the model), where most of the functionality needed to facilitate `undo` (tracking a game’s history) is already present. Note that this is strongly supported by the immutable implementation of the game. Again, follow the control flow from the user clicking to (and within) the backend, and back. Use the “history” to implement undo on the game implementation side. 26 | 27 | Styling: Make it pretty! You can either expand on the CSS provided -- maybe move it to its own file(s) -- or bring in themes. 28 | 29 | 30 | ### Hint: Key Files 31 | To work with this TicTacToe font-end and back-end implementation, you mainly need to understand 4 files: 32 | App.tsx: the main component of this React project. 33 | App.css: the CSS style file for the application. 34 | Cell.tsx: the React.js component for rendering a cell of the board. You may also define a new style file for the Cell component. 35 | game.ts: it defines the data structure for the game including the GameState and the Cell. These structures should likely match with the data structures defined in your backend. 36 | 37 | 38 | ### Hint: Connecting the Frontend to the Backend 39 | This program already has the frontend connected to the backend for you. How this works is that within the Java backend, nanohttpd sets up a server that runs at http://localhost:8080/. It also sets up two pages, /newgame for creating a new game and /play to play a certain move. Then within the TS frontend, which React hosts at http://localhost:3000/, which is where you should redirect your page to, whenever you go to the /newage or /play pages, a request is sent to the nanohttpd server with the relevant info. The server then responds to React with a JSON, with the updated cells. 40 | 41 | 42 | 43 | 44 | 45 | ## HTML/CSS Review 46 | HTML is the standard markup language for Web pages. It is very similar to XML. CSS is the language we use to style an HTML document. CSS describes how HTML elements should be displayed and looked like. There are a lot of good online resources for learning HTML and CSS, e.g., HTML Tutorial (https://www.w3schools.com/html/default.asp) and CSS Tutorial (https://www.w3schools.com/css/default.asp). Please read them if you are not familiar with these materials. 47 | 48 | ## Nanohttpd Review 49 | Nanohttpd is a lightweight Java server that is good for very basic web applications. Because of how small and lightweight it is, it is good for embedding into already existing applications without adding too much size or latency to the project. The backend server of this game is built upon it. To learn more about it, please refer to this Nanohttpd Tutorial (https://www.baeldung.com/nanohttpd). 50 | 51 | ## React.js Review 52 | React.js is a Javascript framework that can be adjusted to work for TypeScript. It is mainly used to make very interactive and dynamic UIs. It allows you to create a complex UI using smaller, isolated pieces of code called “components”. We will use the most basic part of React.js. 53 | 54 | ### A Little History, Why React.js 55 | Stage 1, at the very beginning, most resources shared on the internet were static, i.e., engineers can use HTML to define their static web pages. They could simply update the HTML files (at the server backend) to change the content they wanted to share. However, the webpage has limited interactivity and cannot load data dynamically after being rendered by the browser. 56 | Stage 2, browsers now support Javascript. Engineers can now use Javascript to change their webpages on the client side (browser) to, e.g., add animation, and load data dynamically. E.g., you may find a website that will dynamically update the items as you scroll down the page. 57 | Stage 3, most of the websites are still relying on the technique in Stage 2, even React.js. However, some old Javascript frameworks require you to manually load the data and add/delete HTML elements. This is painful and tedious when your webpage is highly interactive and dynamic. Thus, frameworks like React.js are created. You can easily bind your data and code with the HTML element, and the framework will automatically update the view. 58 | 59 | ### Component 60 | Components are a key element of React.js projects. Each component defines 1) the HTML element about how you want to visualize your data, 2) data bound with this component, e.g., a component is used to render the board, so it should associate with the board data, 3) the code logic for how the data and view will dynamically change or respond to user input. Thus, we can break the web application into small pieces (components), each with its own view definition, data, and implementation. 61 | 62 | A very simple component could look like: 63 | 64 | ![component](images/lab11/component.png) 65 | 66 | Each component will have: 67 | props, an object passed from the caller that holds the data of this component, e.g., in the example, we assume that the parent component of Welcome will pass in the name of this Welcome component instance, which the name will be stored in props, so we can access the name using this.props.name; 68 | state, an object managed by the component itself that can also hold the data of the component, we can use setState() function to update its value, and the view will automatically update accordingly; 69 | render(), the function you must implement which defines how the component will be rendered. In React.js, we use JSX (https://legacy.reactjs.org/docs/introducing-jsx.html) to directly define HTML as code in Javascript or Typescript. In the example, we create a tag, and the name is dynamically obtained from the `this.props.name` object. An advantage of React is that, when the value of name is changed, the view will automatically update. 70 | 71 | Some notes: 72 | props should not be changed by the component itself but instead will be changed by its parent component. On the other hand, state is usually the internal data of the component which should be managed by the component itself. 73 | constructor(props) is not necessary for a component. The only needed one is the render() function 74 | 75 | ### Proxy 76 | One thing this lab makes use of is a TypeScript property called proxy. Proxy essentially tells the front end to route all connections to the base url given in the package.json. For this assignment, the proxy routes to http://localhost:8080/, which is the url that the backend server is running on. This means that when we have a command like await fetch(“/newgame”), this will send a GET request to http://localhost:8080/newgame. 77 | 78 | ![proxy](images/lab11/proxy.png) 79 | 80 | ![proxy2](images/lab11/proxy2.png) 81 | 82 | ### JSON 83 | JSON (JavaScript Object Notation) is a way of formatting data to be easily stored and read by humans. This is similar to a dictionary object with keys and values. An example JSON object is shown below: 84 | 85 | ![jsonFormat](images/lab11/jsonFormat.png) 86 | 87 | This is the format of the information sent from the backend to the frontend. -------------------------------------------------------------------------------- /previous-labs/lab10.md: -------------------------------------------------------------------------------- 1 | # Lab 10: TicTacToe Client/Server 2 | 3 | ## Context 4 | TicTacToe is a two-player game where the players take turns marking the spaces in a three-by-three grid with either X or O. The first player to place three of their marks in a horizontal, vertical, or diagonal row is the winner. More information about the game can be found [here](https://en.wikipedia.org/wiki/Tic-tac-toe). In this recitation, you will work on an implementation of the TicTacToe game. 5 | 6 | This version of TicTacToe is meant to help you set up Homework 6a (User Interface for santorini). It uses a Java backend using a NanoHttpd server and a TS frontend using React.js. This client/server style architecture is commonly used in developing web applications. However, this is a very big topic, we will only cover the essentials for this lab and Homework 6. 7 | 8 | ## Deliverables 9 | - [ ] Extend the implementation to show the current player and winner of the game in the “instructions” panel of the game. 10 | - [ ] Extend the implementation of the game to allow users to undo steps. 11 | - [ ] Change the styling of the game with CSS files (e.g., change colors). 12 | 13 | ## Instructions 14 | Clone the TicTacToe repository from: https://github.com/CMU-17-214/s24-rec10 15 | 16 | Refer to the README’s of the projects therein for set up instructions. After you run the program, you will be able to play the game through the GUI as illustrated in the snippet below from the link http://localhost:3000/. 17 | 18 | ![tictactoe](images/lab10/tictactoe.png) 19 | 20 | 21 | Today’s recitation is all about learning to read and navigate this type of code. The deliverables require you to implement a few very simple improvements, that won’t take you much time at all once you get the hang of how the code is written and structured. So prioritize reading the code and thinking about the flow of information and control. 22 | 23 | Instructions: Right now, the game doesn’t tell the user much; once someone has won, it just stops responding. Let’s add an “instructions” element to the HTML body, with the ID “instructions”. The CSS for this element is already present. The text in this element should indicate whose turn it is, or who has won the game (if applicable). Hint: think about all the places affected by this, in terms of client/view (HTML), and server/controller. How do other elements get updated? 24 | 25 | Undo: The “Undo” button currently does nothing at all. Let’s wire it up. Much like in the previous exercise, think about all the places where changes need to be made. This one will also require you to get into the game implementation (the model), where most of the functionality needed to facilitate `undo` (tracking a game’s history) is already present. Note that this is strongly supported by the immutable implementation of the game. Again, follow the control flow from the user clicking to (and within) the backend, and back. Use the “history” to implement undo on the game implementation side. 26 | 27 | Styling: Make it pretty! You can either expand on the CSS provided -- maybe move it to its own file(s) -- or bring in themes. 28 | 29 | 30 | ### Hint: Key Files 31 | To work with this TicTacToe font-end and back-end implementation, you mainly need to understand 4 files: 32 | App.tsx: the main component of this React project. 33 | App.css: the CSS style file for the application. 34 | Cell.tsx: the React.js component for rendering a cell of the board. You may also define a new style file for the Cell component. 35 | game.ts: it defines the data structure for the game including the GameState and the Cell. These structures should likely match with the data structures defined in your backend. 36 | 37 | 38 | ### Hint: Connecting the Frontend to the Backend 39 | This program already has the frontend connected to the backend for you. How this works is that within the Java backend, nanohttpd sets up a server that runs at http://localhost:8080/. It also sets up two pages, /newgame for creating a new game and /play to play a certain move. Then within the TS frontend, which React hosts at http://localhost:3000/, which is where you should redirect your page to, whenever you go to the /newage or /play pages, a request is sent to the nanohttpd server with the relevant info. The server then responds to React with a JSON, with the updated cells. 40 | 41 | 42 | 43 | 44 | 45 | ## HTML/CSS Review 46 | HTML is the standard markup language for Web pages. It is very similar to XML. CSS is the language we use to style an HTML document. CSS describes how HTML elements should be displayed and looked like. There are a lot of good online resources for learning HTML and CSS, e.g., HTML Tutorial (https://www.w3schools.com/html/default.asp) and CSS Tutorial (https://www.w3schools.com/css/default.asp). Please read them if you are not familiar with these materials. 47 | 48 | ## Nanohttpd Review 49 | Nanohttpd is a lightweight Java server that is good for very basic web applications. Because of how small and lightweight it is, it is good for embedding into already existing applications without adding too much size or latency to the project. The backend server of this game is built upon it. To learn more about it, please refer to this Nanohttpd Tutorial (https://www.baeldung.com/nanohttpd). 50 | 51 | ## React.js Review 52 | React.js is a Javascript framework that can be adjusted to work for TypeScript. It is mainly used to make very interactive and dynamic UIs. It allows you to create a complex UI using smaller, isolated pieces of code called “components”. We will use the most basic part of React.js. 53 | 54 | ### A Little History, Why React.js 55 | Stage 1, at the very beginning, most resources shared on the internet were static, i.e., engineers can use HTML to define their static web pages. They could simply update the HTML files (at the server backend) to change the content they wanted to share. However, the webpage has limited interactivity and cannot load data dynamically after being rendered by the browser. 56 | Stage 2, browsers now support Javascript. Engineers can now use Javascript to change their webpages on the client side (browser) to, e.g., add animation, and load data dynamically. E.g., you may find a website that will dynamically update the items as you scroll down the page. 57 | Stage 3, most of the websites are still relying on the technique in Stage 2, even React.js. However, some old Javascript frameworks require you to manually load the data and add/delete HTML elements. This is painful and tedious when your webpage is highly interactive and dynamic. Thus, frameworks like React.js are created. You can easily bind your data and code with the HTML element, and the framework will automatically update the view. 58 | 59 | ### Component 60 | Components are a key element of React.js projects. Each component defines 1) the HTML element about how you want to visualize your data, 2) data bound with this component, e.g., a component is used to render the board, so it should associate with the board data, 3) the code logic for how the data and view will dynamically change or respond to user input. Thus, we can break the web application into small pieces (components), each with its own view definition, data, and implementation. 61 | 62 | A very simple component could look like: 63 | 64 | ![component](images/lab10/component.png) 65 | 66 | Each component will have: 67 | props, an object passed from the caller that holds the data of this component, e.g., in the example, we assume that the parent component of Welcome will pass in the name of this Welcome component instance, which the name will be stored in props, so we can access the name using this.props.name; 68 | state, an object managed by the component itself that can also hold the data of the component, we can use setState() function to update its value, and the view will automatically update accordingly; 69 | render(), the function you must implement which defines how the component will be rendered. In React.js, we use JSX (https://legacy.reactjs.org/docs/introducing-jsx.html) to directly define HTML as code in Javascript or Typescript. In the example, we create a tag, and the name is dynamically obtained from the `this.props.name` object. An advantage of React is that, when the value of name is changed, the view will automatically update. 70 | 71 | Some notes: 72 | props should not be changed by the component itself but instead will be changed by its parent component. On the other hand, state is usually the internal data of the component which should be managed by the component itself. 73 | constructor(props) is not necessary for a component. The only needed one is the render() function 74 | 75 | ### Proxy 76 | One thing this lab makes use of is a TypeScript property called proxy. Proxy essentially tells the front end to route all connections to the base url given in the package.json. For this assignment, the proxy routes to http://localhost:8080/, which is the url that the backend server is running on. This means that when we have a command like await fetch(“/newgame”), this will send a GET request to http://localhost:8080/newgame. 77 | 78 | ![proxy](images/lab10/proxy.png) 79 | 80 | ![proxy2](images/lab10/proxy2.png) 81 | 82 | ### JSON 83 | JSON (JavaScript Object Notation) is a way of formatting data to be easily stored and read by humans. This is similar to a dictionary object with keys and values. An example JSON object is shown below: 84 | 85 | ![jsonFormat](images/lab10/jsonFormat.png) 86 | 87 | This is the format of the information sent from the backend to the frontend. -------------------------------------------------------------------------------- /previous-labs/lab13.md: -------------------------------------------------------------------------------- 1 | # Lab 13 - Cloud Deployment 2 | 3 | Repo link: [https://github.com/CMU-17-214/s24-lab13](https://github.com/CMU-17-214/s24-lab13) 4 | 5 | In this recitation, you will deploy a version of the TicTacToe game to the 6 | Google Cloud Compute Engine service, allowing you to access it remotely. You can use the same strategy if you want to release your Santorini implementation publicly. 7 | 8 | ## Deliverables 9 | - [ ] Enable the Google Cloud Compute Engine service, and create a virtual machine. 10 | - [ ] Successfully run a Docker image on your cloud virtual machine and show the running site to the TA. 11 | - [ ] Make a change to the code and update the image on the cloud. 12 | 13 | ## Introduction 14 | One of the services provided by Google (and Amazon, Microsoft, etc.) is the 15 | ability to use servers that they have as _virtual machines_. This allows you to 16 | skip a lot of the work needed to assemble your own server, connect it to the 17 | internet, and maintain hardware that might fail. It also allows you to quickly deploy web applications and observe changes as you make them. 18 | 19 | The instructions here are highly manual, and almost all of them can be automated. 20 | This is out of the scope of this course, but other CMU courses focused on DevOps or cloud computing (e.g., 17-346/646, 15-319/619) go into more depth on modern tooling to automate them. 21 | 22 | ## Instructions 23 | 24 | ### Fork the starter repository 25 | 26 | 1. Create your own fork of [the starter repository](https://github.com/CMU-17-214/s24-lab13). 27 | 28 | ### Setting up a new virtual machine 29 | We continue to use the Google Cloud Platform as in Lab 8 and HW5, for which we provided coupons to get free credits. NOTE: We do not have any additional backup coupons. If you have not yet resolved coupon issues, you will not be able to complete this portion of the lab or have to use another billing account. 30 | 31 | 32 | You may or may not have Google Cloud APIs enabled that you need for these 33 | steps. If you do not, choose "Enable" when prompted. 34 | 35 | 2. On the [Google Cloud Console](https://console.cloud.google.com), click the 36 | "Create a VM" button. 37 | 38 | 3. Give your VM a name. 39 | 40 | 4. It is ok to use the default E2 machines, but under the "Machine type" 41 | dropdown select `e2-small` 42 | 43 | ![selectvm](images/lab12/select-vm.png) 44 | 45 | 5. Under "Firewall", select the boxes for "Allow HTTP traffic" and "Allow HTTPS 46 | traffic". 47 | 48 | ![selecttraffic](images/lab12/select-traffic.png) 49 | 50 | 6. Click "Create". 51 | 52 | 7. You will be brought to a screen with a list of VM instances, and should see 53 | your newly created VM, together with an "External IP" that you can use to 54 | connect to it (in this case it's 34.170.46.163). 55 | 56 | ![details](images/lab12/lab13-vm-instances.png) 57 | 58 | ### Connecting to your virtual machine 59 | Similar to lab 8 and homework 5, you will be using the Google Cloud CLI `gcloud` 60 | to run these commands. If you do not have it set up properly, please refer back 61 | to the lab 8 instructions.x 62 | 63 | 8. On your local machine, run `gcloud init` to make sure you are logged in to 64 | the Google Cloud service. 65 | 66 | 9. Log in to your virtual machine with `gcloud compute ssh 67 | --project=[YOUR_PROJECT_ID] [YOUR_VM_NAME]` 68 | 69 | 10. We will be using Docker to deploy this lab. Install the latest version of 70 | Docker on the remote machine using [the instructions 71 | here](https://docs.docker.com/engine/install/debian/#install-using-the-repository). 72 | 73 | ### Sign up for a Docker account and set up a new repository 74 | 75 | 11. Create a new account on [https://hub.docker.com](https://hub.docker.com). This will be used for 76 | creating Docker images and pushing them to Docker Hub for deployment to your new 77 | virtual machine. 78 | 79 | 12. Sign in to Docker Hub. Once you are signed in select "Create repository". For 80 | the name, select something reletavely memorable (e.g., "lab13"). We do not 81 | recommend creating a private repository, or you will have to sign in to your 82 | docker account on the virtual machine as well. 83 | 84 | ### Install Docker on your local computer 85 | 86 | For this lab, we will be compiling, containerizing, and deploying an app to 87 | Docker Hub locally so that they can be easily deployed to the cloud. Note: IF AT 88 | ANY TIME YOU RUN INTO ISSUES HERE, PLEASE JUMP TO THE [EMERGENCY BAILOUT 89 | INSTRUCTIONS](#emergency-bailout-instructions) below. These instructions are 90 | tested and use the virtual machine itself for compilation and containerization, 91 | which is a much less realistic use case, but should allow you to complete the lab. 92 | 93 | 13. Download the Docker Desktop installer from the [Docker Desktop 94 | website](https://docs.docker.com/desktop/), and follow the instructions to 95 | install it. 96 | 97 | 14. From Docker Desktop, sign in to your account using the credentials you 98 | created in the previous step. 99 | 100 | ### Build and deploy a Docker container 101 | 15. On your local machine, clone the repository you forked, and follow the instructions in its README.md to build a Docker image. 102 | 103 | 16. You should be able to see the Docker image you just created with `docker images`. 104 | 105 | 17. Now create a new Docker tag matching your Docker Hub repository name. To do this run 106 | `docker tag lab13 107 | [dockerhub-user-name]/[repository-name]`. `[dockerhub-user-name]/[repository-name]` 108 | should match your user name and the repository name you created on Docker Hub. 109 | 110 | 18. Check that the images you created exist with `docker images`. You should see 111 | two images under the `REPOSITORY` column corresponding to the two you just 112 | created. 113 | 114 | 19. Push the `[dockerhub-user-name]/[repository-name]` image to Docker Hub with 115 | `docker push [dockerhub-user-name]/[repository-name]`. 116 | 117 | 118 | ### Pull the image from Docker Hub on the Google Cloud VM 119 | 20. Log back into the Google Cloud VM you created earlier with the `gcloud compute ssh` command from step 9. 120 | 121 | 21. Download the image you just pushed to Docker Hub onto the VM using `docker pull 122 | [dockerhub-user-name]/[repository-name]`. Check that it exists using `docker 123 | images`. 124 | 125 | Note: If you run into a "permission denied while trying to connect to the Docker daemon socket" error here, run `sudo chmod 666 /var/run/docker.sock`. 126 | 127 | 24. Run the Docker image you just pulled with `docker run -p 80:8080 128 | [dockerhub-user-name]/[repository-name]`. The parameter `-p 80:8080` maps port 8080 of the virtual machine to port 80 of your local machine. You should see the message "Running on 129 | port 8080!" if it is successful and should be able to access the game locally on port 80 (i.e., just `http://`). 130 | 131 | 25. Navigate your web browser to the IP address of the container you created 132 | earlier (i.e., the IP from step 7). You should see the same TicTacToe interface from Lab 7. Skip to step 30 if you got to this point successfully. 133 | 134 | ### EMERGENCY BAILOUT INSTRUCTIONS 135 | 136 | If it turns out that you are having trouble setting up Docker locally, you do 137 | have a virtual Linux machine that you can use to build the Docker 138 | image. Although this is an unrealistic use case, you can get set up with a 139 | container following these instructions. 140 | 141 | 26. Log in to the VM you started on Google Cloud with the `gcloud compute ssh` command from step 9 above. Since you'll be compiling on 142 | the VM, you should first install the additional dependencies using `apt install 143 | maven openjdk-17-jdk nodejs npm`. 144 | 145 | 27. Clone your fork of the starter repository to the Google Cloud VM. Follow the instructions in its README.md to build a Docker image. You do not need to interact with Docker Hub with this method. 146 | 147 | 28. Run the Docker image you just created with `docker run -p 80:8080 lab13`. 148 | 149 | 29. Navigate your web browser to the IP address of the container you created earlier (i.e., the IP from step 7). You should see the same TicTacToe interface from Lab 7. 150 | 151 | ### Make a change to the code 152 | Before you make a change, you can use Ctrl-C to kill the running Docker image on your VM. 153 | 154 | 30. In the forked repository, edit the last line of `front-end/src/App.css` to make playable cells `blue` instead of `red`. 155 | *If you followed the Emergency Bailout Instructions above*, you should make this change on your local computer, commit it, and push it to GitHub. Then, from the Google Cloud VM you can do a `git pull` and the code will be updated. 156 | 157 | 31. From the machine you built the image on, re-build the front end by running `npm run compile` in the `front-end` directory. 158 | 159 | 32. Re-build the Docker image using `docker build -t lab13 --platform linux/amd64 .`. *If you followed the Emergency Bailout Instructions above, skip the next step. 160 | 161 | 33. Update the tag, push to Docker hub, and pull the new image from Docker hub following steps 17 through 21 above. 162 | 163 | 34. Re-run the docker image you just created on the VM using `docker run`. You should see the new website running when you point your web browser to the IP address of the container. 164 | 165 | --- 166 | 167 | Remember to shut down the virtual machine if you do not need it anymore to stop paying credits for it. 168 | -------------------------------------------------------------------------------- /assignments/hw3.md: -------------------------------------------------------------------------------- 1 | # Homework 3: Unit Testing 2 | 3 | In this assignment, you will test the FlashCards system that you expanded in the previous homework. 4 | 5 | This assignment will give you experience creating unit tests against a specification and to cover code with tests as you write it. You will practice following dedicated testing strategies and best practices for unit testing. You will automate your tests with continuous integration and use test coverage tools. 6 | 7 | Specifically, you will perform *structural testing* for the Java implementation and *specification testing* for the TypeScript implementation in your Homework 1 repo. 8 | 9 | ## Starter code 10 | 11 | Continue to work with the code from Homework 1. If you have made any changes to file names or interfaces in the provided code in the directories `cards`, `data`, or `ordering` please restore them to the original names and interfaces and do not change them in this assignment. 12 | 13 | If you prefer a fresh start, you can start over by creating a new branch off the first commit (find id of the first commit with `git log` in branch and follow these [instructions](https://stackoverflow.com/questions/7167645/how-do-i-create-a-new-git-branch-from-an-old-commit)) and then copy over your implementation for `RecentMistakesFirstSorter`. Your hw1 implementation of the command-line parser is not relevant for this homework. 14 | 15 | ## Tasks 16 | 17 | ### Part 1: Infrastructure setup 18 | 19 | Set up the project so that you can write and execute unit tests. We explain *JUnit* and *ts-jest* both in class and provide an example setup in a lab, but you are welcome to use other test frameworks. Make sure that tests are automatically executed with `mvn test` or `npm test` and as part of the GitHub Actions build. We recommend also to identify how you can view test coverage in your IDE or in a generated report. 20 | 21 | 22 | ### Part 2: Specification-base testing (TypeScript) 23 | 24 | Read the public interface specification of every method in the FlashCard **TypeScript** source code, except the exclusions below (don't forget your new `recentMistakesFirstSorter`). Write test cases in **TypeScript** that check whether the implementation covers the specification completely and precisely as best as possible -- even if the implementation is wrong! You may find implementation issues in your newly added `recentMistakesFirstSorter`; make sure to fix such bugs so that your tests all pass. 25 | 26 | That means: 27 | 28 | - Consider the input space and the specification to *intentionally* select valid and invalid inputs as tests. 29 | - Write a test that confirms that everything that is stated works as expected. Guard against "typical" mistakes, such as off-by-one errors or forgetting to implement one part of a multi-faceted specification. 30 | - Do not test what is not specified. Many specifications allow some flexibility and tests should not reject valid implementations of a specification. For example, if the potential nullity of a parameter is not stated, do not write a test that fails if the parameter is `null`. That might be intuitively (and realistically) undesirable behavior, but if it is not in the specification, it should not be tested. (Specifications are often a bit incomplete like that; writing comprehensive specifications can be tedious.) 31 | - Ideally, follow a test design strategy discussed in class, such as *boundary value analysis*. 32 | 33 | The goal is to achieve 100% specification coverage and to write tests that are good at detecting defects. Note that specification coverage is not automatically measurable. 34 | 35 | We will evaluate the quality of your tests by injecting bugs into the implementations to see whether your tests catch them. We will also inject allowed changes to the implementation that do not violate the specification to see whether your tests still pass as expected. You can perform the same kind of experiments yourself to evaluate the quality of your tests by injecting some mistakes yourself (e.g., replacing `<` by `>` or by `<=`, injecting off-by-one errors by adding `+1` to expressions, or checking if the questions and answers are case-insensitive). 36 | 37 | When writing test cases, make sure you follow good practices for test design, as discussed in class and the reading. 38 | 39 | **What to test.** 40 | 41 | Minus the below exceptions, you should test **all TypeScript functions that have specifications** in the original code base, including the new `recentMistakesFirstSorter` that you added. 42 | 43 | You do _not_ need to test: 44 | 45 | - `toString`, `get*` methods: these contain trivial or non-essential functionality. Your tests may, of course, use getter methods. 46 | - `index.ts` and any code written for parsing command line options: these depend heavily on your implementation in homework 1, for which we specified no interface. 47 | - `loadCards` in `store.ts`: this deals with I/O. 48 | - `cardshuffler.ts`: randomness is hard to test. 49 | - `ui.ts`: you will not need to test UI. 50 | 51 | Please note that the last four exclusions would not be industry-standard. They are nontrivial to test, though. We will show you later in the course how you can test such functionality. 52 | 53 | Our reference implementation has about 40 tests. As a hint, for `cardorganizer.ts`, there are many different possible combinations of sorters and repeaters. You should _not_ need to test all combinations to achieve suitable specification coverage! 54 | 55 | 56 | ### Part 3: Structural testing (Java) 57 | 58 | For the Java implementation, write structural tests for the same files you tested in Part 2 to achieve 100% *branch* coverage. You do not need to test files that were excluded in Part 2, nor do you need to test files in the `Achievements` directory. Branch coverage is not required for files that are not part of your testing scope. We will not evaluate your test quality for the source code with injected bugs; the goal is to maximize code coverage for the relevant files. 59 | 60 | As in Part 2, follow the best practices for unit testing. 61 | 62 | **Report coverage** 63 | 64 | Extend the project's build system (Maven's `pom.xml`) so that it creates a coverage report with `mvn site`. Lab 6 provides a template. After you are finished with your tests, when you generate and open a coverage report, you should see 100% branch coverage for the relevant package. 65 | 66 | ### Part 4: Documentation and Reflection 67 | 68 | Add a file `reflection.md` to the root folder of your repository with the following sections: 69 | 70 | In section **Testing strategy** briefly describe whether you followed any specific test case design strategy, such as boundary value analysis, when creating tests. Briefly explain, why you did or did not use these techniques. (about 1 paragraph) 71 | 72 | In section **Specification vs structure testing** briefly reflect on your experience with the two different testing approaches. Was one harder or better than the other for you? (about 1 or 2 paragraphs) 73 | 74 | If you used AI tools such as ChatGPT or Copilot for any part of homework 1 or 2, add a section **AI Tools** describing what you tried them for and whether you found them useful (open ended). 75 | 76 | ## Submitting your work 77 | 78 | Always submit all code to GitHub. Once you have pushed your final code there, submit a link to your final commit in the format `https://github.com/CMU-17-214-Students//commit/` on Canvas (the link identifies the right commit and branch for us, in case you do not work in the main branch). You can get this link easily when you click on the last commit (above the list of files) in the GitHub web interface. 79 | 80 | ## Evaluation 81 | 82 | The assignment is worth 100 points. We will grade the assignment with this rubric: 83 | 84 | * [ ] Submissions that do not provide a link in the expected format can not be graded and will not receive credit. 85 | 86 | **Specification-based Tests in TypeScript (30pt):** 87 | 88 | - [ ] 10: No tests fail on a correct implementation. We will swap out the code in `cards`, `data`, and `ordering` for five different correct implementations of the provided specification. Points will be awarded proportional to the number of implementations that pass your test suite. 89 | - [ ] 20: At least one test fails for each of about 20 bugs we introduce in an otherwise correct implementation. We will run your code against multiple new implementations in `cards`, `data`, and `ordering` that are entirely correct except for a single bug. One or more of your tests should fail because of said bug. Points will be awarded proportional to the number of bugs discovered by your test suite. 90 | 91 | **Structural Tests in Java (20pt):** 92 | 93 | - [ ] 20: Test cases achieve perfect branch coverage on the required classes (10pt partial credit for >90% branch coverage). 94 | 95 | **Test Quality (20pt)** 96 | We will analyze 5 randomly sampled tests: 97 | - [ ] 5: Tests are independent. 98 | - [ ] 5: Tests are cohesive and small. 99 | - [ ] 5: Tests avoid excessive redundancies. 100 | - [ ] 5: Tests are readable (e.g., meaningful names, comments). 101 | 102 | **Infrastructure and style (20pt):** 103 | 104 | * [ ] 5: The project is set up to generate coverage reports for Java (on the command line or in a file) with `mvn site` 105 | * [ ] 5: GitHub Actions runs tests for the TypeScript and Java code automatically. 106 | * [ ] 5: The build passes on GitHub Actions 107 | * [ ] 5: Most commits are reasonably cohesive and most commit messages are reasonably descriptive 108 | 109 | **Reflection (10pt):** 110 | 111 | - [ ] 5: Your writing on your testing strategy demonstrates an understanding of one or more relevant test case design strategies and supports your decision whether or not to adopt these. 112 | - [ ] 5: Your reflection on the two forms of testing shows that you have given thought to the strengths and weaknesses of each based on your experience. The reflection is grounded in concrete experiences, not generic statements. 113 | -------------------------------------------------------------------------------- /previous-assignments/hw2.md: -------------------------------------------------------------------------------- 1 | # Homework 2: Unit Testing 2 | 3 | In this assignment, you will test the FlashCards system that you expanded in the previous homework. 4 | 5 | This assignment will give you experience creating unit tests against a specification and to cover code with tests as you write it. You will practice following dedicated testing strategies and best practices for unit testing. You will automate your tests with continuous integration and use test coverage tools. 6 | 7 | Specifically, you will perform *structural testing* and *specification testing* for the Java implementation in your Homework 1 repo. 8 | 9 | ## Starter code 10 | 11 | Continue to work with the code from Homework 1. If you have made any changes to file names or interfaces in the provided code in the directories `cards`, `data`, or `ordering` please restore them to the original names and interfaces and do not change them in this assignment. 12 | 13 | If you prefer a fresh start, you can start over by creating a new branch off the first commit (find id of the first commit with `git log` in branch and follow these [instructions](https://stackoverflow.com/questions/7167645/how-do-i-create-a-new-git-branch-from-an-old-commit)) and then copy over your implementation for `RecentMistakesFirstSorter`. Your hw1 implementation of the command-line parser is not relevant for this homework. 14 | 15 | ## Tasks 16 | 17 | ### Part 1: Infrastructure setup 18 | 19 | Set up the project so that you can write and execute unit tests. We explain *JUnit* both in class and provide an example setup in a lab, but you are welcome to use other test frameworks. Make sure that tests are automatically executed with `mvn test` and as part of the GitHub Actions build. We recommend also to identify how you can view test coverage in your IDE or in a generated report. 20 | 21 | 22 | ### Part 2: Specification-base testing 23 | 24 | Read the public interface specification of every method in the FlashCard source code, except the exclusions below (don't forget your new `recentMistakesFirstSorter`). Write test cases that check whether the implementation covers the specification completely and precisely as best as possible -- even if the implementation is wrong! You may find implementation issues in your newly added `recentMistakesFirstSorter`; make sure to fix such bugs so that your tests all pass. 25 | 26 | That means: 27 | 28 | - Consider the input space and the specification to *intentionally* select valid and invalid inputs as tests. 29 | - Write a test that confirms that everything that is stated works as expected. Guard against "typical" mistakes, such as off-by-one errors or forgetting to implement one part of a multi-faceted specification. 30 | - Do not test what is not specified. Many specifications allow some flexibility and tests should not reject valid implementations of a specification. For example, if the potential nullity of a parameter is not stated, do not write a test that fails if the parameter is `null`. That might be intuitively (and realistically) undesirable behavior, but if it is not in the specification, it should not be tested. (Specifications are often a bit incomplete like that; writing comprehensive specifications can be tedious.) 31 | - Ideally, follow a test design strategy discussed in class, such as *boundary value analysis*. 32 | 33 | The goal is to achieve 100% specification coverage and to write tests that are good at detecting defects. Note that specification coverage is not automatically measurable. 34 | 35 | We will evaluate the quality of your tests by injecting bugs into the implementations to see whether your tests catch them. We will also inject allowed changes to the implementation that do not violate the specification to see whether your tests still pass as expected. You can perform the same kind of experiments yourself to evaluate the quality of your tests by injecting some mistakes yourself (e.g., replacing `<` by `>` or by `<=`, injecting off-by-one errors by adding `+1` to expressions, or checking if the questions and answers are case-insensitive). 36 | 37 | When writing test cases, make sure you follow good practices for test design, as discussed in class and the reading. 38 | 39 | **What to test.** 40 | 41 | Minus the below exceptions, you should test **all functions that have specifications** in the original code base, including the new `recentMistakesFirstSorter` that you added. 42 | 43 | You do _not_ need to test: 44 | 45 | - `toString`, `get*` methods: these contain trivial or non-essential functionality. Your tests may, of course, use getter methods. 46 | - `Main.java` and any code written for parsing command line options: these depend heavily on your implementation in homework 1, for which we specified no interface. 47 | - `loadCardsFromFile()` function in `CardLoader.java`: this deals with I/O. 48 | - `CardShuffler.java`: randomness is hard to test. 49 | - `UI.java`: you will not need to test UI. 50 | 51 | Please note that the last four exclusions would not be industry-standard. They are nontrivial to test, though. We will show you later in the course how you can test such functionality. 52 | 53 | Our reference implementation has about 40 tests. As a hint, for `CardOrganizer.java`, there are many different possible combinations of sorters and repeaters. You should _not_ need to test all combinations to achieve suitable specification coverage! 54 | 55 | 56 | ### Part 3: Structural testing 57 | 58 | Write structural tests in **Java** for the files under the `achievement` folder to achieve 100% *branch* coverage. You do not need to test `UI.java` which is where achievements are displayed. You do not need to achieve a branch coverage goal for any other code, and we will not evaluate your test quality for the achievements with injected bugs. 59 | 60 | *Hint:* You can call the `isAchieved` method for an AchievementType Enum as follows: `AchievementType.CORRECT.isAchieved(x, y)` where `x` is a long and `y` is a `CardDeck`. Changing CORRECT to a different enum will allow you to test each `isAchieved` method. 61 | 62 | As in Part 2, follow the best practices for unit testing. 63 | 64 | **Report coverage** 65 | 66 | Extend the project's build system (Maven's `pom.xml`) so that it creates a coverage report with `mvn site`. The third lab provides a template. After you are finished with your tests, when you generate and open a coverage report, you should see 100% branch coverage for the `edu.cmu.cs214.hw1.achievement` package. 67 | 68 | ### Part 4: Documentation and Reflection 69 | 70 | Add a file `reflection.md` to the root folder of your repository with the following sections: 71 | 72 | In section **Testing strategy** briefly describe whether you followed any specific test case design strategy, such as boundary value analysis, when creating tests. Briefly explain, why you did or did not use these techniques. (about 1 paragraph) 73 | 74 | In section **Specification vs structure testing** briefly reflect on your experience with the two different testing approaches by providing examples from your code. Was one harder or better than the other for you? (about 1 or 2 paragraphs) 75 | 76 | If you used AI tools such as ChatGPT or Copilot for any part of homework 1 or 2, add a section **AI Tools** describing what you tried them for and whether you found them useful (open ended). 77 | 78 | ## Submitting your work 79 | 80 | Always submit all code to GitHub. Once you have pushed your final code there, submit a link to your final commit in the format `https://github.com/CMU-17-214//commit/` on Canvas (the link identifies the right commit and branch for us, in case you do not work in the main branch). You can get this link easily when you click on the last commit (above the list of files) in the GitHub web interface. 81 | 82 | ## Evaluation 83 | 84 | The assignment is worth 100 points. We will grade the assignment with this rubric: 85 | 86 | * [ ] Submissions that do not provide a link in the expected format can not be graded and will not receive credit. 87 | 88 | **Specification-based Tests (30pt):** 89 | 90 | - [ ] 10: No tests fail on a correct implementation. We will swap out the code in `cards`, `data`, and `ordering` for five different correct implementations of the provided specification. Points will be awarded proportional to the number of implementations that pass your test suite. 91 | - [ ] 20: At least one test fails for each of about 20 bugs we introduce in an otherwise correct implementation. We will run your code against multiple new implementations in `cards`, `data`, and `ordering` that are entirely correct except for a single bug. One or more of your tests should fail because of said bug. Points will be awarded proportional to the number of bugs discovered by your test suite. 92 | 93 | **Structural Tests (20pt):** 94 | 95 | - [ ] 20: Test cases achieve perfect branch coverage on the required classes (10pt partial credit for >90% branch coverage). 96 | 97 | **Test Quality (20pt)** 98 | We will analyze 5 randomly sampled tests: 99 | - [ ] 5: Tests are independent. 100 | - [ ] 5: Tests are cohesive and small. 101 | - [ ] 5: Tests avoid excessive redundancies. 102 | - [ ] 5: Tests are readable (e.g., meaningful names, comments). 103 | 104 | **Infrastructure and style (20pt):** 105 | 106 | * [ ] 5: The project is set up to generate coverage reports (on the command line or in a file) with `mvn site` 107 | * [ ] 5: GitHub Actions runs tests for the Java code automatically. 108 | * [ ] 5: The build passes on GitHub Actions 109 | * [ ] 5: Most commits are reasonably cohesive and most commit messages are reasonably descriptive 110 | 111 | **Reflection (10pt):** 112 | 113 | - [ ] 5: Your writing on your testing strategy demonstrates an understanding of one or more relevant test case design strategies and supports your decision whether or not to adopt these. 114 | - [ ] 5: Your reflection on the two forms of testing shows that you have given thought to the strengths and weaknesses of each based on your experience. The reflection is grounded in concrete experiences, not generic statements. 115 | -------------------------------------------------------------------------------- /assignments/hw5.md: -------------------------------------------------------------------------------- 1 | # Homework 5: Concurrency 2 | 3 | In this assignment you will work with concurrency in a Node backend. You will get experience with writing asynchronous code, and with error handling. 4 | 5 | ## Starter code 6 | 7 | Find the starter code with the GitHub Classroom link on Canvas. 8 | 9 | You will work on a semi-completed program *SmilingFaces* to analyze faces in Wikipedia pages -- for example are more people smiling in pictures of the Carnegie Mellon Wikipedia page or in the University of Pittsburgh wikipedia page? In the web application, you can enter a *topic* for which a Wikipedia page exists and the program will identify all images in the page and determine with an ML model whether the picture contains smiling faces. It can also collect the pictures from other Wikipedia pages linked heavily from the target page ("include top neighbor topics"). 10 | 11 | The starter code already handles all the communication with Wikipedia and the Google Cloud Vision API, but the backend code is currently written synchronously (which is actually quite difficult to do and very unusual for Node code). As a consequence the backend can only respond to a single request at a time and it is very slow. The provided implementation is also bad at error handling. 12 | 13 | The code consists of two related projects: The backend *express* implementation in the root directory and the frontend *React* implementation in directory `frontend`. Compile and run the code as follows: 14 | 15 | * First, build the frontend 16 | * run `npm install` in the `frontend/` directory. (Note: deprecation and security vulnerability warnings here are expected) 17 | * `npm run build` in `frontend/` to build the frontend, which will result in static pages in `frontend/build/` 18 | * Second, build and run the backend 19 | * run `npm install` in the root directory 20 | * `npm run compile` builds the backend, resulting in Javascript code in `dist/` as usual 21 | * Make sure that you are signed into the Google Cloud API using `gcloud` (same as Lab 8) 22 | * `npm run start` runs the server which you can then access at `http://localhost:8080` 23 | 24 | The backend serves the frontend code in the root of the web server but also provides API endpoints for starting a job (`POST /job`) and for getting results of a job (`GET /job/:id`) that both communicate in JSON format (using the [Long Running Operation with Polling Pattern](http://restalk-patterns.org/long-running-operation-polling.html)). The frontend will make requests to the APIs to update the state within the page. If a job is not completed on the first request, it will check every second for updates. 25 | 26 | In the user interface in the web browser you can enter a topic and start the analysis. Note that the response will take a very long time if you analyze any nontrivial pages. Analyzing the topic "Carnegie Mellon University" gathers and analyzes 30 images without neighboring pages (and many more with neighbors), which easily takes 30 seconds to respond. A good test page might be "David Tepper" which has only a single image and takes about 2 seconds to analyze. 27 | 28 | ## Tasks 29 | 30 | **Concurrency in the backend.** Rewrite the backend to perform computations concurrently. We have the following requirements of the final implementation: 31 | 32 | * The server makes requests to Wikipedia and the Google Cloud API concurrently, speeding up responses significantly. 33 | * The server can answer multiple requests concurrently (i.e., multiple calls to `/job` and `/job/:id`). 34 | * The server reports an error when more than 5 jobs are processed concurrently asking users to try again later. Reject additional requests with HTTP error code 503. 35 | * The server never makes more than 5 concurrent requests to Wikipedia and never more than 5 concurrent requests to the Google Cloud API in order to not overload those servers (this limit is shared by all jobs). 36 | * If multiple topics are analyzed, the server does not wait until all images are collected from all topics, but starts analyzing images as soon as the images from each topic are identified. 37 | 38 | **Error handling.** Make the implementation robust to errors. Specifically we expect you to handle the following kind of errors: 39 | 40 | * When connections to Wikipedia or the Google Cloud API fail (error, timeout, or invalid results) retry two more times after a short wait of one second. 41 | * When connections to Wikipedia or the Google Cloud API fail and cannot be recovered or any other computations fail, report an error message to the frontend gracefully. Your server should still be able to handle 5 concurrent jobs and up to 5 concurrent backend requests afterward. 42 | * The backend validates inputs received from the frontend. Reject empty and invalid inputs with HTTP error code 400. 43 | 44 | **What to change:** This homework can be completed by only making changes to `backend.ts`, `visionapi.ts`, and `wikipediaapi.ts`. We plan to automate some testing of your code, as such, do NOT change the `Connections` interface and the signature of the `smilingFacesBackend` function. Also do not change the protocol between the backend and frontend. If we cannot grade your submission because you change any of these, we will assign zero points to that specific rubric item. Make all external calls through the APIs in `Connections` and do not make web calls with any other API. You may, and probably should, develop your own abstractions on top of the functions in `Connections`. 45 | 46 | ## Submitting your work 47 | 48 | As usual, submit all your changes to GitHub. Once you have pushed your final code, submit a link to your final commit on Canvas. A link will look like `https://github.com/CMU-17-214-Students//commit/`. You can get to this link easily when you click on the last commit (above the list of files) in the GitHub web interface. 49 | 50 | ## Evaluation 51 | 52 | This assignment is worth 100 points. We will grade the assignment with the rubric below. Submissions that do not provide a link in the expected format can not be graded and will not receive credit. 53 | 54 | Concurrency: 55 | 56 | * [ ] [10 points] The backend code makes use of concurrency to speed up computations for getting Wikipedia requests 57 | * [ ] [10 points] The backend code makes use of concurrency to speed up computations for analyzing images with the Google Cloud API. 58 | * [ ] [10 points] The backend code can process multiple jobs concurrently. 59 | * [ ] [10 points] The backend successfully completes computations and provides the results through the API. 60 | * [ ] [10 points] The backend rejects additional new jobs when processing 5 jobs concurrently with HTTP error code 503 61 | * [ ] [10 points] The backend correctly limits concurrency to at most 5 concurrent requests each to Wikipedia and Google. 62 | * [ ] [10 points] The backend can process images after images are identified from a topic, independent of other topics also to be analyzed. 63 | 64 | Error handling: 65 | 66 | * [ ] [5 points] The backend implements a retry mechanism for failed Wikipedia and Google connections, that makes two more attempts with a one second wait after each failed attempt. 67 | * [ ] [5 points] The backend recovers gracefully from failed Wikipedia and Google connections, reporting an error message to the client. Errors do not reduce the ability to perform work concurrently. 68 | 69 | Others: 70 | 71 | * [ ] [10 points] The backend code compiles on GitHub Actions. 72 | * [ ] [5 points] Commit messages are reasonably cohesive and have reasonable messages. 73 | * [ ] [5 points] The code is free of severe readability and style issues. 74 | 75 | ## Appendix: Hints and Tooling Tips 76 | 77 | **How to start:** The code is functional as provided. Identify where the *sync* functions from `Connections` are called and understand how they are used. Incrementally turn synchronous functions in asynchronous ones by changing return type `T` to `Promise` and updating the implementation of the function and its call sides accordingly. 78 | 79 | It is difficult to make only local changes as incremental refactorings. It might be easier to change the entire WikipediaAPI or VisionAPI class at once. If necessary, comment out the vision API steps first and just get images from topics with and without neighboring topics. It might be useful to write simple tests for the calls to the Wikipedia API that can run outside the backend, e.g., with jest or with a simple main function just calling `newWikipediaAPI(new DefaultConnection()).getImageLinksFromTopic("David Tepper")`. 80 | 81 | **Implementation suggestions:** We recommend to use promises or async/await. It might be a good starting point to turn the provided connection functions with callbacks into promises. Beyond that you might find `Promise.all` useful. 82 | 83 | You can consider streams (`ReadableStream` of the Web Streams) for some of the work, but it is not required. 84 | 85 | The homework changes can all be fully implementing with plain Node code. Consider using the Proxy pattern to modularize error handling. If you like, you can use external libraries, such as `p-limit` or one of the many retry libraries. 86 | 87 | The execution order of concurrent code may not always be intuitive. Consider using a debugger or using print statements in the code to follow the execution. 88 | 89 | **Testing suggestions:** Writing tests may be useful, but is not required in this assignment. There are good opportunities for testing with stubs in the backend; the backend code is written in a way to make this testing easy by avoiding global functions. We do not suggest to test frontend code. 90 | 91 | A basic testing infrastructure is already setup in directory `tests/`, but there is only one test implemented. The example test uses stubs, but you can also run tests against Wikipedia and Google Cloud by just using the `DefaultConnection` class. Of course you can also test parts of your implementation without starting express, for example by writing tests for the functions in `wikipediaapi.ts`. 92 | 93 | While you are not required to automate tests, we will use tests in the style of the provided examples for grading. 94 | 95 | **Tooling suggestions:** If you want to send requests to the backend without running the frontend, you can send requests on the command line, such as 96 | 97 | ```bash 98 | curl -X POST -H "Content-Type: application/json" -d '{"name": "David Tepper", "withNeighbors": false}' http://localhost:8080/job 99 | ``` 100 | 101 | With `npx tsc --watch` you can keep the TypeScript compiler running in a terminal and it will automatically compile changes whenever you safe a file. In a second terminal, `npx nodemon .` it will restart your application (the backend) after every change, that is, whenever the compiler has produced a new version. The test runner `jest` watches changes by default. 102 | -------------------------------------------------------------------------------- /previous-labs/lab01.md: -------------------------------------------------------------------------------- 1 | # Lab 1: Course Infrastructure Setup 2 | 3 | During this course, you will become familiar with several popular and industry-relevant software engineering tools, including IDEs, build systems, and automated style checkers. In this lab, you will set up your environment and explore some tools for getting started with Java. The instructions are unusually long, because we try to provide more detailed help for common problems. If you encounter problems along the way, look back at the instructions, work through problems with others, and seek help from the TAs during the lab session. 4 | 5 | 6 | 7 | ## Deliverables 8 | 9 | - [ ] Locally clone your Homework 1 Git repository, fix a typo in the `README.md` file ("assigment" -> "assignment") and commit and push the change. 10 | - [ ] Install Java 21, Maven, and an IDE of your choice. Run `java --version` to verify it is version 21. 11 | - [ ] Show that you can compile and run the Java starter code of homework 1 on your machine. 12 | 13 | 14 | 15 | ## Setting Up Your Repo 16 | 17 | In this lab, we will work with the starter code from Homework 1. Each student in 17-214/514 is assigned a GitHub repo per homework assignment. You can create it by following the GitHub Classroom link in the description of [Homework 1 on Canvas](https://canvas.cmu.edu/courses/39213/assignments/675175). 18 | 19 | - If you do not have *git* yet, follow the [download instructions](https://git-scm.com/downloads). 20 | - If you do not have a *GitHub* account yet, [create one](https://github.com/). 21 | - Follow the GitHub classroom link on Canvas/Piazza to create your own GitHub repository with the starter code for homework 1. 22 | 23 | **Setting up your Personal Access Token.** Before cloning the repository, you should set up your own personal access token; otherwise, you might get an invalid username or password error. GitHub removes these every year, so even if you have made one in the past, you may need to recreate it. You can follow the [instructions](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) for the general outline on how and where to create a personal access token. Some things to note: 24 | 25 | - You can name it something like 17214s24 or whatever you’d like 26 | - Set the expiration date to be some time past the end of the semester (e.g. 05/31/24), so that you don’t have to remake it again this semester 27 | - You can select all of the options if you’d like and read more about what they do [here](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps). At the very least, make sure you have the **repo, workflow, user, project** scopes selected. 28 | - **Important:** Once you generate the token, make sure you save it somewhere safe and accessible to you before you leave the page. You will need to use it as your password to log-in and you won’t be able to see it again after leaving the page. 29 | 30 | **Cloning the Repository.** Navigate to your own remote repository, and then click on the green “code” button to copy the URL of this remote repository so that you can clone it. 31 | 32 | We recommend to learn to use *git* on the command line, but you can also the integration in your IDE or [GitHub Desktop](https://desktop.github.com/). To clone the repository from the command line run the following in a terminal: `git clone ` 33 | 34 | This will download the entire repository to your computer. If you are prompted to input your username and password, make sure that you use your personal access token you created above as the password. 35 | 36 | 37 | 38 | ## Java Setup 39 | 40 | ### Installing Java 41 | 42 | Download and install Java 21. The language used in this class is Java 21. Several vendors provide implementations of Java 21, if in doubt choose the open-source OpenJDK 21. 43 | 44 | Installing the right version of Java can sometimes be a bit tricky. If you already use a package manager for your platform (homebrew, apt, snap, scoop, etc) installing Java with that tool is probably the easiest. Below are detailed instructions, but feel free to skim/skip. 45 | 46 | *Note for Windows users:* We recommend installing [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) (Windows Subsystem for Linux) and using it for all your development environments installations and future assignments when following this guide. 47 | 48 | **Installing Java using homebrew on MacOS.** Run `brew install openjdk@21` and run the command from the output to create a symbolic link. See [these instructions](https://medium.com/@manvendrapsingh/installing-many-jdk-versions-on-macos-dfc177bc8c2b) for a detailed reference. 49 | 50 | **Manual installation and other operating systems.** 51 | 52 | - MacOS. Download the MacOS tar.gz archive from the [OpenJDK website](https://jdk.java.net/archive/). Untar the archive (double click), and move the contained directory (named something like jdk-21.0.1.jdk) to the /Library/Java/JavaVirtualMachines/ directory 53 | - Linux. If possible, please really use the package manager of your distribution. It will be much easier. Instructions for a manual installation on Ubuntu can be found [here](https://computingforgeeks.com/install-java-jdk-21-openjdk-21-on-ubuntu/). 54 | - Windows. To install OpenJDK, download the Windows zip file from the [OpenJDK website](https://jdk.java.net/java-se-ri/21), and follow the instructions at [this StackOverflow post ](https://stackoverflow.com/questions/52511778/how-to-install-openjdk-11-on-windows/52531093#52531093)to correctly set Windows environment variables. Alternatively, if you wish to just use an install wizard, [download and install the Oracle JDK](https://www.oracle.com/java/technologies/downloads/#java21). 55 | 56 | **Managing multiple Java installations.** If you already have existing different versions of Java installed and want to keep them, you can use [jEnv](http://jenv.be) to help manage your installations. As another option, you can set the JAVA_HOME environment variable in your ~/.zshrc or ~/.bash_profile or Windows configuration to point to Java 21 folder (e.g., `export JAVA_HOME=$(/usr/libexec/java_home -v21)`; if you choose this approach, you’ll need to modify the number that comes after -v if you ever want to switch your Java version). If you’re interested in switching between Java versions (not needed in this course), see [here](https://medium.com/@manvendrapsingh/installing-many-jdk-versions-on-macos-dfc177bc8c2b) under the section “Switching JDKs” for instructions on how to do so. 57 | 58 | *Checkpoint:* Confirm your Java installation by inspecting the output of the command `java -version` and `javac -version`. You should see something similar to: *openjdk version "21.0.1" 2023-10-17.* The major version should be 21, any vendor and patch version is okay. 59 | 60 | ### Installing Maven 61 | 62 | We use Maven as the build tool and package manager for Java in this course. Install a recent version of Maven. You can follow the instructions in [this link](https://www.baeldung.com/install-maven-on-windows-linux-mac) and verify that Maven 3.8.7 or newer is installed.[^1] More information about Maven can be found [here](https://maven.apache.org/what-is-maven.html). 63 | 64 | For Mac users, you might find it easiest to install maven using homebrew: `brew install maven` 65 | 66 | Explore the `pom.xml` file to see how the project is currently configured. 67 | 68 | *Checkpoint:* In the java subdirectory of your local homework 1 repository, try to run `mvn install` which will download dependencies and compile the code. You can either type `mvn install` in the terminal or click the Maven tab on the bottom left, scroll down to “install” and press the triangle. 69 | 70 | ### VSCode for Java 71 | 72 | VSCode is a popular IDE for Java which we recommend for this course, but you are free to choose other IDEs, such as IntelliJ and Eclipse, which are more advanced if you are solely developing in Java. However, we will later introduce and develop in TypeScript in the course, so using VSCode will save you from having to switch between IDEs which can be tedious. 73 | 74 | Install VSCode following [instructions](https://code.visualstudio.com/) on its homepage or use your operating system's package manager. 75 | 76 | *Checkpoint:* You can explore the source files of the cloned repository in the IDE. 77 | 78 | **Navigate to the sidebar and look for the extensions symbol (5th from the top) and search for “Extension Pack for Java” and install it locally**. This extension includes linting, test running and debugging, support for Maven (the build automation tool we use for Java projects in this class), and a few other helpful extensions. 79 | 80 | You need to have Java 21 installed for this project. Do not downgrade your Java version if you are asked to, this will break your project. 81 | 82 | *Checkpoint:* You can explore the source files in the IDE. 83 | 84 | **Running a Java program in VSCode.** Once you have successfully opened the project and installed Maven, you should be able to view all the starter source files. Try building the program and run the main class. 85 | 86 | 87 | 88 | ![img](figures/vscode-run.png) 89 | 90 | To run a program go to the main class (`Main.java`), you should see a *Run | Debug* prompt above the main method. Click *Run*. You will be able to view the run result at the bottom. You can interact with this program by replying on the console and hitting “enter”. 91 | 92 | Alternatively, you can open the `Main.java` file and then open the *Run and Debug* tab on the left sidebar (4th from the top). Pressing Run and Debug will have the same effect as pressing Debug on the prompt above the main method. 93 | 94 | **Passing a command-line argument (you might find this helpful for HW1).** If you want to pass an argument to the program from within VSCode, click *“Create a launch.json file”*. This will open a file containing all of the run configurations. If you’d like to modify this in the future, you can find it in the .vscode folder. 95 | 96 | ![img](figures/vscode-launchconfig.png) 97 | 98 | Under the configuration named `Launch Main`, you can add the attribute `args` and supply it with your arguments. For example `"args": "--help"`. You can also supply multiple arguments in the same line: `"args": ["--arg1", "value1", "--arg2", "value2", …]` 99 | 100 | For more information on launch configurations and Java debugging in VSCode, see [here](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations). 101 | 102 | ### Checkstyle for Java 103 | 104 | We preconfigured the project with the style checker *Checkstyle*. It is automatically executed as part of compiling and packaging the project with `mvn site (on the command line or in the IDE). 105 | 106 | If you’d like to be able to run Checkstyle through VSCode’s UI, you can search for and install the [“Checkstyle for Java” extension](https://code.visualstudio.com/docs/java/java-linting#_checkstyle). To use this extension: Right click the `checkstyle.xml` file and select *“Set the Checkstyle Configuration File”* . Then right click on the file you want to check and select *“Check Code with Checkstyle”*. You can view Checkstyle violations on the problems tab near your terminal. 107 | 108 | *Checkpoint*: Test Checkstyle by renaming one method to start with a capital letter (against Java's style guidelines) and it should complain. A neat thing that this plugin does is automatically lint your code as you write it. You can test this out by opening the “problems” tab and making further changes. 109 | 110 | 111 | 112 | ## Turning in Your Work 113 | 114 | For finishing this lab (and all homeworks), you are required to submit your work by pushing changes to your repositories on GitHub. 115 | 116 | The minimal instructions to submit code with Git on the command line are: 117 | 118 | ````bash 119 | git add 120 | git commit -m "" 121 | git push 122 | ```` 123 | 124 | **git add** adds files to the staging area, **git commit** saves everything on the staging area along with the given commit message, and **git push** records local commits to the remote repository. After pushing changes you should see them on GitHub. 125 | 126 | If you are new to Git you will learn to better use it throughout the semester, including best practices and more advanced functionality like branches. We provide more detailed instructions in a [separate document](git-basics.md) but encourage you to find documentation and tutorials on your own too. 127 | 128 | 129 | 130 | 131 | 132 | [^1]: If you choose to use the instructions linked, the `chown -R root:wheel Downloads/apache-maven*` command should actually be `sudo chown -R root:wheel Downloads/apache-maven*`. If you run into issues with adding Maven to your environment path, try using `~/.zshrc` instead of `~/.zshenv`. 133 | --------------------------------------------------------------------------------