10 |
11 | ## Homework - Exercise #0
12 |
13 | 1. Find team members to groups of 2-3 people. Together, come up with a team name (Team names must be url-safe). We will setup a team on Github and Moodle for you. Kudos for a team name with a corresponding emoji.
14 | 2. Make a copy of this repository (using a second remote). Ensure that each member of your team has sufficient access. :star:
15 | 3. Replace the content of this `README.md` with your individual content. Here's a Github [README.md template](https://github.com/othneildrew/Best-README-Template) and there are more [awesome READMEs](https://github.com/matiassingers/awesome-readme) out there. :star:
16 |
17 | You can also have a look on the community checklist to get inspiration:
18 |
19 |
20 | 
21 |
22 | ### How to submit homework
23 |
24 | You have to create a feature branch first, commit your code and push it to your
25 | copy of the homework repository. Then create a pull request with your feature
26 | branch as the target branch and request a review from your teachers.
27 |
28 | 
29 |
30 | Make sure that you *watch* the original homework repository. That's where we
31 | update exercise descriptions. Keep your own copy up-to-date by merging in new
32 | commits of the original repository.
33 |
34 | 
35 |
36 | Do not submit lengthy pull request. Pull requests with a large `diff` in
37 | `Files changed` tab are difficult to review. If you want to get good feedback on
38 | your pull requests, don't push unrelated changes.
39 |
--------------------------------------------------------------------------------
/archive/1/README.md:
--------------------------------------------------------------------------------
1 | # Exercise \#1
2 |
3 | Implement a simple todo app with VueJS.
4 |
5 | Each item in the todo app should:
6 |
7 | * Edit: display a form to update the todo
8 | * Save: update the todo and display it
9 | * Cancel: cancel the form submission
10 | * Delete: delete the todo
11 |
12 | Here is how the result should look like:
13 |
14 | 
15 |
16 | Use computed properties and events where possible and make use of the component
17 | pattern.
18 |
19 | Get extra praise for implementing the "Add todo" button! :heart:
20 |
--------------------------------------------------------------------------------
/archive/1/components/List.js:
--------------------------------------------------------------------------------
1 | export default Vue.component('list', {})
2 |
--------------------------------------------------------------------------------
/archive/1/components/ListItem.js:
--------------------------------------------------------------------------------
1 | export default Vue.component('list-item', {})
2 |
--------------------------------------------------------------------------------
/archive/1/exercise-vuejs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/1/exercise-vuejs.gif
--------------------------------------------------------------------------------
/archive/1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/archive/1/index.js:
--------------------------------------------------------------------------------
1 | import List from './components/List.js'
2 | import ListItem from './components/ListItem.js'
3 |
4 | new Vue({
5 | el: '#app',
6 | data: {
7 | todos: [
8 | { id: '1', message: 'Foo', },
9 | { id: '2', message: 'Bar', },
10 | { id: '3', message: 'Baz', }
11 | ] // feel free to put the `todos` array where you find it most suitable
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/archive/2/README.md:
--------------------------------------------------------------------------------
1 | # Exercise \#2
2 |
3 | Write test for your existing code.
4 |
5 | This is not exactly test driven development, because you do the implementation
6 | first and add the automated tests later. Don't worry, we keep the test driven
7 | development for the upcoming exercises. However, do mutant testing in order to
8 | double-check if your tests actually fail for a bug in your code.
9 |
10 | 1. Add a linter to your project, e.g. `eslint` or `prettier`.
11 | 2. Test your components with `jest` and `vue-test-utils`. Here is some
12 | inspiration how the tests could be structured:
13 | 
14 | 3. Setup a build server. If your linter or your tests fail, that should fail the
15 | build. Popular choices for open source projects are [Travis CI](https://travis-ci.com/)
16 | or [Circle CI](https://circleci.com/)
17 | 4. Integrate your build server status into your repository, i.e. your build
18 | server tests each of your pull requests and you can see the result on the
19 | pull request.
20 | 
21 | You can also add a badge to your `README.md`.
22 | 
23 | 5. Request a review from @roschaefer
24 | 6. Request a review from a member of another team
25 | 7. Review a pull request of another group. Either "Request Changes" or
26 | "Approve". Give suggestions by clicking on the line of code that needs
27 | improvement.
28 | 
29 |
30 |
31 | If you copy code from other groups, please give credit to them in your commit
32 | messages.
33 |
--------------------------------------------------------------------------------
/archive/2/build-server-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/2/build-server-badge.png
--------------------------------------------------------------------------------
/archive/2/build-server-checks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/2/build-server-checks.png
--------------------------------------------------------------------------------
/archive/2/code-suggestions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/2/code-suggestions.png
--------------------------------------------------------------------------------
/archive/2/terminal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/2/terminal.png
--------------------------------------------------------------------------------
/archive/3/README.md:
--------------------------------------------------------------------------------
1 | # Exercise \#3
2 |
3 | Test-drive the development of a GraphQL server.
4 |
5 | **Deadline is December 4th, 2019**
6 |
7 | ### tl;dr
8 |
9 | 1. Show that you can can setup an [apollo-server](https://www.apollographql.com/docs/apollo-server/).
10 | 2. Test your backend with [apollo-server-testing](https://www.apollographql.com/docs/apollo-server/testing/testing/).
11 | 3. Implement [JWT](https://jwt.io/) and have at least one query which requires authentication.
12 | 4. Add backend testing to your build server pipeline.
13 | 5. Request a review from @roschaefer
14 | 6. Request a review from sb. else
15 |
16 | Note that it is **not required** that you connect your frontend with your
17 | backend.
18 |
19 |
20 | ### Suggested workflow and some inspiration
21 |
22 | * Test-drive your implementation. As a first step, you can just write down the
23 | documentation, e.g.
24 | ```js
25 | it.todo("behaves in a specified way")
26 | ```
27 | will create a to-be-implemented test case with this description.
28 | * Pro tip: I run queries and mutations against an apollo server and check the
29 | response with jest's [`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject)
30 | matcher all the time. You can use it to check for both `data` and `errors`.
31 | * Have a look into the [Human Connection](https://github.com/human-connection/human-connection)
32 | repo to learn how we implement JWT and write backend tests.
33 | * Be creative with your type definitions in your schema and have some custom
34 | types. You could e.g. implement CRUD operations for your types.
35 | * If you want to connect your frontend with your backend (totally optional) it
36 | would be wise if one of your types is a `Todo`.
37 | * Here is some inspiration: 
38 |
39 |
40 | ### Optional (will be part of an upcoming exercise)
41 | * Implement a permission layer around your app. Use [graphql-shield](https://github.com/maticzav/graphql-shield)
42 | and [graphql-middleware](https://github.com/prisma-labs/graphql-middleware).
43 | * Here is some inspiration how your test cases could look like:
44 | 
45 | * Connect your frontend with your backend via [vue-apollo](https://github.com/vuejs/vue-apollo).
46 | So if you update a todo in your frontend, it sends a graphql mutation to the
47 | backend.
48 |
49 |
50 | If you copy code from other groups, please give credit to them in your commit
51 | messages.
52 |
--------------------------------------------------------------------------------
/archive/3/crud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/3/crud.png
--------------------------------------------------------------------------------
/archive/3/permissions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/3/permissions.png
--------------------------------------------------------------------------------
/archive/4/README.md:
--------------------------------------------------------------------------------
1 | # Exercise \#4
2 |
3 | Connect your database with Neo4J
4 |
5 | **Deadline is December 18th, 2019**
6 |
7 | 1. Refactor your backend so that all the data is stored in[Neo4J](https://neo4j.com/).
8 | 2. You are allowed to use a query builder like [neo4j-graphql-js](https://github.com/neo4j-graphql/neo4j-graphql-js)
9 | but at least one of your mutations and queries should access the database
10 | directly with [Neo4j JS driver](https://github.com/neo4j/neo4j-javascript-driver)
11 | and a custom cypher statement.
12 | 3. Your objects in the database should be connected in some way. If you have a
13 | relationship like
14 | ```
15 | (:User)<-[:ASSIGNED]-(:Todo)
16 | ```
17 | then this query should return todos and user objects:
18 | ```gql
19 | query {
20 | todos {
21 | assignedTo {
22 | name
23 | }
24 | }
25 | }
26 | ```
27 | 4. Implement a filter (`WHERE` in cypher).
28 | 5. Implement some ordering (`ORDER BY` in cypher).
29 | 6. Implement pagination (`SKIP` and `LIMIT` in cypher).
30 | 7. Implement an update mutation that uses `MERGE`.
31 | 8. Write backend tests for all of the above.
32 | 9. Request a review from @roschaefer.
33 | 10. Request a review from sb. else.
34 |
35 | If you copy code from other groups, please give credit to them in your commit
36 | messages.
37 |
--------------------------------------------------------------------------------
/archive/5/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Exercise \#5
3 |
4 | Learn how to use graphql-middlewares and start programming with NuxtJS.
5 |
6 | **Deadline is January 8th, 2020**
7 |
8 | 1. Optional tasks of exercise #3 are now required: Implement a permission
9 | layer around your app. Use [graphql-shield](https://github.com/maticzav/graphql-shield)
10 | and [graphql-middleware](https://github.com/prisma-labs/graphql-middleware).
11 | Here is some inspiration how your test cases could look like:
12 | 
13 | 2. Refactor your backend and frontend to show something different than just
14 | todos and users. Be creative.
15 | 3. Do a remote pair-programming session. You can choose any pairing partner,
16 | either from our course or you can also ask our open-source community.
17 | 4. Record your pair-programming session and publish it. Choose any software you
18 | want. If you don't like being on the web, disable your webcam and save the
19 | video as "unlisted". I recommend [PeerTube](https://joinpeertube.org/) to
20 | host the video but there is also this commercial platform called YouTube as
21 | an alternative. Send a link to your recorded video to htw@roschaefer.de.
22 | 5. Write backend tests.
23 | 6. Request a review from @roschaefer.
24 | 7. Request a review from sb. else.
25 |
26 | ### Teaching goal
27 |
28 | The point of exercise 3. and 4. is to socialize and see how easy it is to find
29 | people from around the world who like to program with you and learn with you.
30 | Even a recording of a pairing session can be interesting learning material.
31 | Think of people who don't have access to public education, e.g. studying at a
32 | university like you do.
33 |
34 | Also, if you get stuck, people can help out. Often, developers wait for too long
35 | before they ask for help. It causes a lot of frustration and this particular
36 | situation happened for a team while working on exercise \#3. Asking for help in
37 | our community chat is quick and usually there is always somebody around who can
38 | help out: https://human-connection.org/discord
39 |
40 | ### Optional exercises
41 |
42 | 1. Create a NuxtJS app and write a couple of different page components. Your
43 | page component should have some level of nesting. Like `/nested.vue`,
44 | `/nested/index.vue` and `/nested/_id.vue`.
45 | 2. Connect your frontend with your backend via [apollo-module](https://github.com/nuxt-community/apollo-module).
46 | So if you update a data object in your frontend, it sends a graphql mutation
47 | to the backend.
48 | 3. Make use of apollo-module's [authentication helpers](https://github.com/nuxt-community/apollo-module#authentication)
49 | and have at least one page component which requires authentication.
50 | 4. Write frontend tests, mock `this.$apollo` and respond with some mocked data or simulate an error.
51 |
52 |
53 | If you copy code from other groups, please give credit to them in your commit
54 | messages.
55 |
--------------------------------------------------------------------------------
/archive/6/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Exercise \#6
3 |
4 | Start programming with NuxtJS and learn fullstack testing.
5 |
6 | **Deadline is January 22th, 2020**
7 |
8 | 1. Create a NuxtJS app and write a couple of different page components. Your
9 | page component should have some level of nesting. Like `/nested.vue`,
10 | `/nested/index.vue` and `/nested/_id.vue`.
11 | 2. Connect your frontend with your backend via [apollo-module](https://github.com/nuxt-community/apollo-module).
12 | So if you update a data object in your frontend, it sends a graphql mutation
13 | to the backend.
14 | 3. Make use of apollo-module's [authentication helpers](https://github.com/nuxt-community/apollo-module#authentication).
15 | 4. Implement a page component which requires authentication. Make sure that your
16 | frontend returns a HTTP status code 403 if you are not allowed to see that
17 | page.
18 | 5. Request a review from @roschaefer.
19 | 6. Request a review from sb. else.
20 |
21 | ### How to get help
22 |
23 | If you have troubles with the setup or dependencies, feel free to get in touch
24 | with the open-source community: https://human-connection.org/discord
25 | Most contributors know NuxtJS very well and can help with the setup.
26 |
27 |
28 | ### Optional exercises
29 |
30 | 1. Write frontend tests, mock `this.$apollo` and respond with some mocked data
31 | or simulate an error.
32 | 2. Write a fullstack test with https://www.cypress.io/.
33 | 3. Record and publish a pair-programming :heart_eyes:
34 |
35 | If you copy code from other groups, please give credit to them in your commit
36 | messages.
37 |
--------------------------------------------------------------------------------
/archive/Exam/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *.aux
3 | svg-inkscape/*
4 | code/graphql/node_modules/
5 | code/vuejs/node_modules/
6 |
7 |
--------------------------------------------------------------------------------
/archive/Exam/code/css/example.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/archive/Exam/code/graphql/index.js:
--------------------------------------------------------------------------------
1 | const { ApolloServer, gql } = require('apollo-server')
2 |
3 | const typeDefs = gql`
4 | type Student {
5 | id: ID
6 | firstname: String
7 | lastname: String
8 | fullname(reverse: Boolean): String
9 | }
10 |
11 | type Query {
12 | student(id: ID): Student
13 | allStudents: [Student]
14 | }
15 | `
16 | const students = [
17 | { id: '1', firstname: 'Bob', lastname: 'Builder' },
18 | { id: '2', firstname: 'Alice', lastname: 'Wonderland' },
19 | ]
20 |
21 | const resolvers = {
22 | Query: {
23 | student: (parent, args, context, resolveInfo) => {
24 | console.log('Query.student:', parent, args)
25 | return students.find(student => student.id === args.id)
26 | },
27 | allStudents: (parent, args, context, resolveInfo) => {
28 | console.log('Query.allStudents:', parent, args)
29 | return students
30 | },
31 | },
32 | Student: {
33 | fullname: (parent, args, context, resolveInfo) => {
34 | console.log('Student.fullname:', parent.id, args)
35 | if (args.reverse) return [parent.lastname, parent.firstname].join(', ')
36 | return [parent.firstname, parent.lastname].join(' ')
37 | }
38 | }
39 | }
40 |
41 | const server = new ApolloServer({ typeDefs, resolvers });
42 | server.listen().then(({ url }) => {
43 | console.log(`🚀 Server ready at ${url}`);
44 | });
45 |
--------------------------------------------------------------------------------
/archive/Exam/code/graphql/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "exam-apollo-server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "dependencies": {
7 | "apollo-server": "^2.19.0"
8 | },
9 | "devDependencies": {},
10 | "scripts": {
11 | "start": "node index.js"
12 | },
13 | "author": "",
14 | "license": "ISC"
15 | }
16 |
--------------------------------------------------------------------------------
/archive/Exam/code/review/apollo-server/index.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken');
2 | const { AuthenticationError } = require('apollo-server-errors');
3 | const typeDefs = require('./typedefs.js')
4 | const { todos, users } = require('./data.js')
5 |
6 | const resolvers = {
7 | Query: {
8 | // ommitted for simplicity
9 | },
10 | Mutation: {
11 | deleteToDo: (object, input) =>{
12 | const decrypted = decryptedToken(input.token);
13 | todos.splice(input.index, 1);
14 | },
15 | updateToDo: (object, input) => {
16 | const decrypted = decryptedToken(input.token);
17 | todos[input.index].title = input.title;
18 | },
19 | loginUser: (object, params) => {
20 | const { username, password} = params;
21 | let theUser = users.find(
22 | user => user.username === username );
23 |
24 | if(theUser === undefined){
25 | throw new AuthenticationError(
26 | "Username undefined"
27 | );
28 | }
29 | if(theUser.password !== password){
30 | throw new AuthenticationError(
31 | "Wrong password"
32 | )
33 | }
34 | return {token : jwt.sign(theUser, "12345")};
35 | }
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/archive/Exam/code/review/apollo-server/resolvers.js:
--------------------------------------------------------------------------------
1 | const {AuthenticationError} = require("apollo-server-errors");
2 | const jwt = require('jsonwebtoken');
3 | const users = require('./users')
4 |
5 | const resolvers = {
6 | Query: {
7 | todos: async (parent, args, context) => {
8 | const currentUser = context.user.name;
9 | let page = 0;
10 | let size = 20;
11 | if (typeof args.page != "undefined") page = args.page;
12 | if (typeof args.size != "undefined") size = args.size;
13 |
14 | console.log('INFO - Got ALL_TODOS_QUERY from user ' + currentUser);
15 | const session = context.driver.session();
16 | const todosQuery = await session.run(
17 | 'MATCH (t:Todo)-[:BELONGS]->(u:User)\n' +
18 | 'WHERE u.name = ' + userName + '\n' +
19 | 'RETURN t, u\n' +
20 | 'ORDER BY t.text DESC\n' +
21 | 'SKIP ' + (page * size) + '\n'
22 | 'LIMIT ' + limit + '\n');
23 | const todos = todosQuery.records.map(todo => {
24 | let abc = todo.get('t').properties;
25 | abc.user = todo.get('u').properties;
26 | return abc;
27 | });
28 | return todos;
29 | }
30 | },
31 | Mutation: {
32 | loginUser: (object, params) => {
33 | const { username, password} = params;
34 | let theUser = users.find(user => user.username === username );
35 |
36 | if(theUser === undefined){
37 | throw new AuthenticationError(
38 | "Username undefined"
39 | );
40 | }
41 | if(theUser.password !== password){
42 | throw new AuthenticationError(
43 | "Wrong password"
44 | )
45 | }
46 | return {token : jwt.sign(theUser, "12345")};
47 | }
48 | deleteTodo: async (parent, args, context) => {
49 | todos.pop()
50 | return true
51 | }
52 | }
53 | };
54 |
55 | module.exports = resolvers;
56 |
--------------------------------------------------------------------------------
/archive/Exam/code/review/apollo-server/typedefs.js:
--------------------------------------------------------------------------------
1 | export default const typeDefs = `
2 | type todos {
3 | title: String
4 | }
5 | type Query {
6 | todos: [todos]
7 | users: [User]
8 | }
9 | type User {
10 | name: String!
11 | password: String!
12 | id: Int
13 | }
14 | type Mutation {
15 | addToDo(title: String!, token: String!): [todos]
16 | deleteToDo(index: Int!, token: String!): [todos]
17 | updateToDo(title: String!, index: Int!, token: String!): [todos]
18 | loginUser(username: String!, password: String!): AuthPayLoad!
19 | }
20 | input UserLoginInput {
21 | username: String!
22 | password: String!
23 | }
24 | type AuthPayLoad {
25 | token: String!
26 | }
27 | `
28 |
--------------------------------------------------------------------------------
/archive/Exam/code/review/component-tests/1.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import ListItem from './ListItem'
3 | const wrapper = mount(ListItem)
4 |
5 | describe('given a `todo`', () => {
6 | it('renders todo text', () => {
7 | expect(wrapper.text()).toContain('Save');
8 | })
9 |
10 | it('should show an input field', () => {
11 | expect(wrapper.emitted('edit', () => {
12 | wrapper.contains('input').tobe(false)
13 | }))
14 | })
15 |
16 | describe('click on delete button', () => {
17 | expect(wrapper.emitted('delete'))
18 | })
19 | })
20 |
21 |
--------------------------------------------------------------------------------
/archive/Exam/code/review/component-tests/2.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import ListItem from './ListItem.vue'
3 |
4 | describe('ListItem', () => {
5 | describe('given an `item`', () => {
6 | const dummy = { id: "1", message: "Foo" };
7 | const wrapper = mount(ListItem, { propsData: { item: dummy } });
8 |
9 | it('init with dummy parameter', () => {
10 | expect(wrapper.vm.item).toEqual(dummy);
11 | });
12 |
13 | it('renders item', () => {
14 | var foundItem = wrapper.find('#item-description');
15 | var itemDescription = wrapper.vm.item.id + '. ' + wrapper.vm.item.message;
16 | expect(foundItem.text()).toEqual(itemDescription);
17 | });
18 |
19 | describe('testing `Delete` button', () => {
20 | it('click on button emits delete event', () => {
21 | //wrapper.vm.deleteItem();
22 | wrapper.find('#button-delete').trigger('click');
23 | //console.log(wrapper.emitted());
24 | var itemToDelete = wrapper.emitted('delete-item')[0][0];
25 | //console.log(itemToDelete);
26 | expect(itemToDelete.message).toEqual(wrapper.vm.item.message);
27 | expect(itemToDelete.message).toEqual(dummy.message);
28 | });
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/archive/Exam/code/vuejs/Example.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ message }}
8 |
9 |
12 |
13 | {{ exclaimedMessage }}
14 |
15 |
16 |
17 |
18 |
44 |
--------------------------------------------------------------------------------
/archive/Exam/code/vuejs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuejs",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "devDependencies": {
7 | "@vue/cli": "^4.1.2",
8 | "@vue/cli-service-global": "^4.1.2"
9 | },
10 | "scripts": {
11 | "start": "vue serve Example.vue"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/archive/Exam/exam.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Systems-Development-and-Frameworks/homework/f0ee9706ac724c9992e255d5bd8ab62b59096525/archive/Exam/exam.pdf
--------------------------------------------------------------------------------
/archive/Exam/exam.tex:
--------------------------------------------------------------------------------
1 | \documentclass[
2 | % addpoints, ngerman
3 | addpoints,a4paper,ngerman,answers
4 | ]{exam}
5 | %\documentclass[12pt,addpoints,answers]{exam} % To print with answers
6 | \usepackage{amsmath}
7 | \usepackage{graphicx}
8 | \usepackage{setspace}
9 | \usepackage{fancybox}
10 | \usepackage{svg}
11 | \usepackage{listings}
12 | \usepackage{todonotes}
13 | \usepackage{subfig}
14 |
15 | \pointpoints{Punkt}{Punkte}
16 | \renewcommand{\solutiontitle}{\noindent\textbf{Lösung:}\enspace}
17 |
18 |
19 | \chqword{Frage}
20 | \chpgword{Seite}
21 | \chpword{Punkte}
22 | \chsword{Erreicht}
23 | \chtword{Gesamt}
24 |
25 | \usepackage[ngerman]{babel}
26 | \lstset{basicstyle=\ttfamily,
27 | showstringspaces=false,
28 | showspaces=false,
29 | showtabs=false,
30 | showstringspaces=false,
31 | commentstyle=\color{red},
32 | keywordstyle=\color{blue}
33 | }
34 | \lstdefinelanguage{JavaScript}{
35 | keywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, if, in, while, do, else, case, break},
36 | keywordstyle=\color{blue}\bfseries,
37 | ndkeywords={class, export, boolean, throw, implements, import, this},
38 | ndkeywordstyle=\color{darkgray}\bfseries,
39 | identifierstyle=\color{black},
40 | sensitive=false,
41 | comment=[l]{//},
42 | morecomment=[s]{/*}{*/},
43 | commentstyle=\color{purple}\ttfamily,
44 | stringstyle=\color{red}\ttfamily,
45 | morestring=[b]',
46 | morestring=[b]"
47 | }
48 |
49 |
50 |
51 |
52 |
53 | \pagestyle{headandfoot}
54 | \firstpageheadrule
55 | \firstpageheader{Name:} { } {Systems-Development and Frameworks}
56 | \firstpagefooter{}{Endklausur, Seite \thepage\ von \numpages}
57 | {}
58 | \runningheader{Name:} { } {Systems-Development and Frameworks}
59 | \runningfooter{}{Endklausur, Seite \thepage\ von \numpages}
60 | {}
61 | \runningheadrule
62 | \runningfootrule
63 |
64 | %%%%% Cover page
65 |
66 | \coverfirstpageheader{
67 | HTW Berlin \\ Angewandte Informatik
68 | }{}{
69 | Systems-Development\\ and Frameworks
70 | }
71 |
72 | \runningheadrule
73 | \runningfootrule
74 | \onehalfspacing
75 | \newcommand{\tf}[1][{}]{%
76 | \fillin[#1][0.25in]%
77 | }
78 |
79 | \begin{document}
80 | %\maketitle
81 | \pointsinmargin % To print points in margin
82 | \boxedpoints % or \bracketedpoints
83 |
84 | \begin{coverpages}
85 | \hrule
86 | \hrule
87 | \noindent
88 | \begin{tabular}{@{}p{.4\textwidth}@{\hspace{2cm}}p{.4\textwidth}@{}}
89 | \\
90 | Name:\enspace\hrulefill & Matrikelnummer:\enspace\hrulefill
91 | \end{tabular}
92 | \noindent
93 | \vspace{5em}
94 |
95 | \setlength{\fboxsep}{2em}
96 | \noindent\fbox{
97 | \parbox{\textwidth - 4em}{
98 | Deine Note in der Endklausur sagt nichts über dein Talent als
99 | Fullstack-EntwicklerIn aus. Viele wesentliche Fähigkeiten können nicht in
100 | einer schriftlichen Prüfung bewertet werden, z.B. selbstständiges Lernen,
101 | Wissensvermittlung, Einfühlungsvermögen und Hilfsbereitschaft innerhalb
102 | eines Teams.\\
103 |
104 | Der Zweck dieser Endklausur ist es, eine Zahl für jede Teilnehmerin und
105 | jeden Teilnehmer zu ermitteln. Das ist eine formelle Anforderung der
106 | Universität.\\
107 |
108 | Abgesehen davon dient die Klausur als Motivation für euch zum Lernen.
109 |
110 | \begin{center}
111 | Viel Erfolg! \\
112 | Robert Schäfer
113 | \end{center}
114 |
115 | }}
116 |
117 | \vspace{3em}
118 | \begin{center}
119 | \gradetable[h][questions]
120 |
121 | % Or use \gradetable[v][questions]
122 | \end{center}
123 |
124 | \end{coverpages}
125 |
126 | \begin{questions}
127 |
128 |
129 | \question Project Management
130 | \begin{parts}
131 | \part[1] Vervollständige den folgenden Satz:
132 | Das Motto unseres Kurses ist: ``Le\_\_n and S\_\_\_e''
133 |
134 | \part[1]
135 | Was ist der Busfaktor? Schreibe eine Definition auf.
136 | \fillwithdottedlines{4em}
137 |
138 | \part[1]
139 | Was ist besser? Ein möglichst hoher Busfaktor oder ein niedriger Busfaktor?
140 | \begin{choices}
141 | \choice Ein niedriger Busfaktor ist besser.
142 | \choice Ein hoher Busfaktor ist besser.
143 | \end{choices}
144 |
145 | \part[3]
146 | Wie kann der Wissenstransfer im Team gewährleistet werden?
147 | Nenne mindestens drei unterscheidbare Methodiken, die wir im Kurs kennen
148 | gelernt haben:
149 | \fillwithdottedlines{8em}
150 |
151 | \part[4]
152 | Wobei helfen automatisierte Software-Tests?
153 |
154 | Software-Tests eignen sich um:
155 | \begin{checkboxes}
156 | \choice Abhängigkeiten im Quellcode zu erkennen und zu vermeiden
157 | \choice das Laufzeitverhalten zu beschreiben, z.B. Komplexitätsklassen von Algorithmen
158 | \choice die Korrektheit des Quellcodes zu beweisen
159 | \choice Schnittstellen zu definieren
160 | \choice Software-Regressionen zu vermeiden
161 | \choice Projektabnahmen durch den Kunden oder Projektleiter zu ersetzen
162 | \choice das Verhalten der Anwendung zu dokumentieren
163 | \choice die Wartung des Quellcodes abzusichern, z.B. beim Refactoring
164 | \end{checkboxes}
165 |
166 | \part
167 | Wir haben in unserem Kurs einen Software-Test als ``positiv'' definiert, wenn
168 | er fehlschlägt. (Also ähnlich wie ein ``positiver'' medizinischer Test,
169 | welcher bedeutet, dass eine Testperson wahrscheinlich krank ist, z.~B.
170 | HIV-positiv.)
171 |
172 | Falsch implementierte Software-Tests können zu folgenden Problemen führen:
173 | \begin{choices}
174 | \choice Es können Sicherheitslücken entstehen.
175 | \choice Es kommt zu Verzögerungen beim Ausrollen der Anwendung (Deployment).
176 | \choice Die Endbenutzer können betroffene Funktionen der Anwendung nicht mehr nutzen.
177 | \choice Das Team verliert an Disziplin und das Vertrauen in Software-Testing.
178 | Es beginnt, Änderungen am Quellcode zu akzeptieren, obwohl der Build-Server
179 | fehlgeschlagen ist.
180 | \end{choices}
181 |
182 | \begin{subparts}
183 | \subpart[2]
184 | Welche dieser Probleme entstehen durch ``falsch-positive'' Software-Tests?
185 |
186 | Auswahl: \fillin
187 | \subpart[2]
188 |
189 | Welche dieser Probleme entstehen durch ``falsch-negative'' Software-Tests?
190 |
191 | Auswahl: \fillin
192 | \end{subparts}
193 |
194 | \part[2]
195 | Mit welcher Technik kann man ``falsch-negativen'' Tests vorbeugen? Anders
196 | gefragt: Wie kann man sicherstellen, dass ein Software-Test überhaupt einen
197 | Fehler aufzeigen würde?
198 | \fillwithdottedlines{8em}
199 |
200 | \end{parts}
201 |
202 |
203 | \question Git
204 | \begin{parts}
205 | \part[1]
206 | Ensteht bei einem \texttt{git commit --amend} eine neue commit id?
207 | \begin{choices}
208 | \choice Ja
209 | \choice Nein
210 | \end{choices}
211 | \part[1]
212 | Wie könnte man ein \texttt{git commit --amend} wieder rückgängig machen?
213 | \fillwithdottedlines{4em}
214 |
215 | \part
216 | Folgendes Szenario: Wir haben vergessen, rechtzeitig einen ``Feature-branch''
217 | zu erstellen und jetzt zeigt der \texttt{master} branch auf den commit mit
218 | der ID~\texttt{G}. Abbildung~\ref{fig:git:initial} visualisiert den
219 | \texttt{git} Graph zu diesem Zeitpunkt.
220 |
221 | Unser Ziel ist es, nachträglich einen Feature-Branch zu erstellen, damit wir
222 | einen ``Pull Request'' mit einer gewünschten Liste an commits erstellen
223 | können. Außerdem wollen wir unseren lokalen \texttt{master} branch auf den
224 | Stand des \texttt{origin/master} zurücksetzen. Als letztes strukturieren wir
225 | die commits mit einem interaktiven \texttt{rebase} um, mit dem Ziel, unserem
226 | Team das ``Code-Review'' zu erleichtern.
227 |
228 | \begin{figure}[h]
229 | \centering
230 | \includesvg[width=0.8\textwidth]{git/initial.svg}
231 | \caption{Visualisierung des initialen \texttt{git}-Graphen.}
232 | \label{fig:git:initial}
233 | \end{figure}
234 |
235 | \newpage
236 | \begin{subparts}
237 | \subpart[1]
238 | Im ersten Schritt führen wir den folgenden Befehl aus:
239 | \begin{lstlisting}
240 | git branch feature-branch
241 | \end{lstlisting}
242 | Wie verändert sich der \texttt{git}-Graph? Skizziere den Graphen:
243 | \makeemptybox{16em}
244 |
245 | \subpart[1]
246 | Wir setzen den \texttt{master} auf den Stand des \texttt{origin/master} zurück
247 | mit diesem Befehl:
248 | \begin{lstlisting}
249 | git reset origin/master --hard
250 | \end{lstlisting}
251 | Skizziere den \texttt{git}-Graphen:
252 | \makeemptybox{16em}
253 |
254 | \subpart[1]
255 | Wir wechseln zurück auf den branch \texttt{feature-branch} mit diesem Befehl:
256 | \begin{lstlisting}
257 | git checkout feature-branch
258 | \end{lstlisting}
259 | Wie verändert sich der \texttt{git}-Graph? Skizziere den Graphen:
260 | \makeemptybox{16em}
261 |
262 | \newpage
263 | \subpart[1]
264 | Schließlich beginnen wir ein interaktives \texttt{rebase} mit diesem Befehl:
265 | \begin{lstlisting}
266 | git rebase origin/master --interactive
267 | \end{lstlisting}
268 | Danach öffnet sich der Editor mit einer Liste von commits. Welche commits
269 | befinden sich in dieser Liste?
270 | \fillwithdottedlines{3em}
271 |
272 | \subpart[1]
273 | Die Liste der commits wird neu sortiert, einige commits entfernt oder
274 | mit \texttt{squash} verschmolzen. Das sieht so aus:
275 | \begin{lstlisting}
276 | pick F commit message of F
277 | pick D squash commit message of D
278 | squash G with commit message of G
279 | \end{lstlisting}
280 | Wenn jetzt diese Änderung am ``rebase-log'' abgeschlosssen werden, dann wird
281 | der \texttt{rebase}-Prozess ausgelöst. Dieser Prozess wird aber einmal
282 | unterbrochen. Warum?
283 | \fillwithdottedlines{8em}
284 |
285 | \subpart[2]
286 | Wie sieht der \texttt{git}-Graph letztendlich aus? Wenn neue commits
287 | entstanden sind, wähle einen beliebigen, freien Buchstaben als neue Commit ID.
288 | Skizziere den finalen Graphen:
289 | \makeemptybox{16em}
290 |
291 |
292 | \end{subparts}
293 |
294 | \end{parts}
295 |
296 |
297 |
298 | \question Funktionale Programmierung
299 |
300 | \begin{parts}
301 | \part[2] Was sind ``higher order functions''?
302 | \fillwithdottedlines{6em}
303 | \newpage
304 |
305 | \part[2] Im folgenden Code-Beispiel wird eine Funktion namens
306 | \texttt{higherOrderFunction} deklariert, die Argumente der Funktion heißen
307 | \texttt{some, arguments, you, can} und \texttt{choose}. Bitte schreibe
308 | eine Implementierung, sodass die Funktion \emph{ganz offensichtlich} zu einer
309 | ``higher-order function'' wird.
310 | \begin{lstlisting}[extendedchars=true,basicstyle=\ttfamily,language=JavaScript]
311 | function higherOrderFunction(some, arguments, you, can, choose) {
312 | // Write down any implementation, which obviously turns this
313 | // function into a higher order function.
314 | // ...
315 |
316 |
317 |
318 |
319 | // return ?
320 | // If you want, return something
321 | }
322 | \end{lstlisting}
323 |
324 | \part
325 | Die folgenden Code-Beispiele enthalten unnötige temporäre Zustände. Zustände
326 | sind immer ungünstig, weil sie mögliche Fehlerquellen sein können. Wie können
327 | die folgenden Code-Beispiele umgeschrieben (refactored) werden, um die unnötigen
328 | Zustände zu eliminieren? Das Verhalten des Codes sollte sich nicht wesentlich
329 | verändern.
330 |
331 | Es gibt für jedes Code-Beispiel einen Punkt, wenn die richtige Funktion von
332 | \texttt{Array.prototype} ausgewählt wird.
333 | Für jedes korrekte Refactoring eines Code-Beispiels gibt es einen weiteren
334 | Punkt. Geringfügige Syntax-Fehler führen zu keinem Punktabzug.
335 | \begin{subparts}
336 | \subpart[2]
337 | \begin{lstlisting}[extendedchars=true,basicstyle=\ttfamily,language=JavaScript]
338 | function findTodo(todos, id){
339 | let found
340 | for (i = 0; i < todos.length; i++) {
341 | if (todos[i].id === id) {
342 | found = todos[i]
343 | break
344 | }
345 | }
346 | return found
347 | }
348 |
349 | function refactoredFindTodo(todos, id){
350 | // your code goes here...
351 |
352 |
353 |
354 |
355 |
356 |
357 | // return ?
358 | }
359 | \end{lstlisting}
360 | \newpage
361 | \subpart[2]
362 | \begin{lstlisting}[extendedchars=true,basicstyle=\ttfamily,language=JavaScript]
363 | function incrementIds(ids, addition = 1) {
364 | var retArray = []
365 | for (var i = 0; i < ids.length; i++) {
366 | retArray.push(ids[i] + addition)
367 | }
368 | return retArray
369 | }
370 |
371 |
372 | function refactoredIncrementIds(ids, addition = 1) {
373 | // your code goes here
374 |
375 |
376 |
377 |
378 |
379 | // return ?
380 | }
381 | \end{lstlisting}
382 | \end{subparts}
383 | \end{parts}
384 |
385 |
386 | \question Authorization and Authentication
387 | \begin{parts}
388 | \part[2]
389 | Was bedeuten die Begriffe ``Authorization'' und ``Authentication''? Füge im
390 | folgenden Lückentext die beiden Begriffe an der richtigen Stelle ein:\\
391 |
392 | Bei der \fillin[][2in] wird festgestellt, welcher Benutzer eine Anfrage an den
393 | Server sendet. Sobald der Benutzer bekannt ist, klärt die \fillin[][2in] ob
394 | der Benutzer auch auf eine Ressource zugreifen darf.
395 | \part[1]
396 | Werden die Nutzdaten (``Payload'') eines ``JWT Bearer token'' verschlüsselt
397 | übertragen?
398 | \begin{choices}
399 | \choice Ja
400 | \choice Nein
401 | \end{choices}
402 | \part[1]
403 | Wenn der Schlüssel zur Überprüfung der Signatur der JSON-Web-Token erneuert
404 | wird, werden daraufhin alle bis dahin ausgelieferten Token ungültig?
405 | \begin{choices}
406 | \choice Ja
407 | \choice Nein
408 | \end{choices}
409 | \end{parts}
410 |
411 | \clearpage
412 |
413 | \question GraphQL and Apollo-Server
414 |
415 | \begin{parts}
416 | \part[4] Welche Probleme löst GraphQL in Bezug auf REST?
417 | \begin{checkboxes}
418 | \choice Daten können in einer Graph-Datenbank gespeichert werden.
419 | \choice Die Anzahl der Anfragen wird minimiert.
420 | \choice HTTP-Caching Mechanismen werden besser ausgenutzt .
421 | \choice Der Server wird robuster gegenüber Denial-of-Service Angriffen.
422 | \choice Die Menge der ausgetauschen Daten pro Anfrage (der Traffic) wird minimiert.
423 | \choice Die API kann automatisch dokumentiert werden
424 | \choice Auf dem Client kann die Benutzeroberfläche automatisch aktualisiert werden.
425 | \choice Die Anzahl der Datenbank-Abfragen wird minimiert.
426 | \end{checkboxes}
427 | \part
428 | Die Methodensignatur eines resolvers enthält vier Argumente, nämlich
429 | \texttt{parent}, \texttt{args}, \texttt{context} und \texttt{resolveInfo}.
430 | \begin{subparts}
431 | \subpart[1]
432 | Sollte das Argument \texttt{context} in allen resolvern gleich sein?
433 | \begin{choices}
434 | \choice Ja
435 | \choice Nein
436 | \end{choices}
437 | \subpart[2]
438 | Wozu wird das Argument \texttt{resolveInfo} genutzt?
439 | \fillwithdottedlines{6em}
440 | \end{subparts}
441 |
442 | \part[2]
443 | Schau auf die Implementierung eines Apollo-Servers in
444 | Abbildung~\ref{fig:apollo-server} auf Seite~\pageref{fig:apollo-server}.
445 |
446 | \begin{figure}[h]
447 | \begin{lstlisting}[language=bash]
448 | query {
449 | student(id: "2") {
450 | id
451 | fullname(reverse: true)
452 | }
453 | }
454 | \end{lstlisting}
455 | \caption{GraphQL query}
456 | \label{fig:graphql-query}
457 | \end{figure}
458 | Wenn wir die GraphQL Anfrage in Abbildung~\ref{fig:graphql-query} an den
459 | Server schicken, mit welcher Antwort reagiert der Server? Schreibe das JSON
460 | Dokument auf.
461 | \makeemptybox{18em}
462 |
463 | \part Was schreibt der Server als Ausgabe aufs Terminal? Schreibe die
464 | \texttt{console.log} Ausgaben auf. Folgende korrekte Angaben werden bewertet:
465 | \begin{subparts}
466 | \subpart[1] Korrekte Auswahl, welche Log-Ausgaben überhaupt erreicht werden
467 | \subpart[1] Korrekte Anzahl aller Ausgaben
468 | \subpart[1] Korrekte Reihenfolge der Ausgaben
469 | \subpart[1] Korrekter Wert des Arguments \texttt{parent}
470 | \subpart[1] Korrekter Wert des Arguments \texttt{args}
471 | \end{subparts}
472 | \makeemptybox{18em}
473 | \begin{figure}[t!]
474 | \lstinputlisting[
475 | basicstyle=\ttfamily,
476 | numbers=left,
477 | numberstyle=\footnotesize,
478 | numbersep=3em,
479 | extendedchars=true,
480 | language=JavaScript
481 | ]{code/graphql/index.js}
482 | \caption{Implementierung eines Apollo-Servers}
483 | \label{fig:apollo-server}
484 | \end{figure}
485 | \end{parts}
486 |
487 |
488 | \clearpage
489 |
490 | \question Neo4J
491 | \begin{parts}
492 |
493 | \part
494 | Wie wird das relationale Datenmodell in ein graph-basiertes Datenmodell
495 | übertragen? Nimm als Beispiel eine Neo4J-Datenbank.
496 | \begin{subparts}
497 | \subpart[1] Tabellen-Namen werden zu: \fillin
498 | \subpart[1] Tabellen-Spalten werden zu: \fillin
499 | \subpart[1] Einträge in Tabellen (Zeilen) werden zu: \fillin
500 | \subpart[1] Fremdschlüssel zwischen Einträgen werden zu: \fillin
501 | \end{subparts}
502 |
503 | \part
504 | Betrachte die \texttt{cypher} Anfrage:
505 | \begin{lstlisting}
506 | MATCH (node)-[*]->(yetAnotherNode) RETURN *
507 | \end{lstlisting}
508 | \begin{subparts}
509 | \subpart[2]
510 | Was bedeutet der Stern in den eckigen Klammern im ``pattern'' dieser
511 | query?
512 | \fillwithdottedlines{4em}
513 | \subpart[1]
514 | Ist so eine Anfrage auch in einer relationalen Datenbank mit SQL möglich?
515 | \begin{choices}
516 | \choice Ja
517 | \choice Nein
518 | \end{choices}
519 | \end{subparts}
520 |
521 | \part[2] Können in einer Neo4J-Datenbank Fremdschlüssel auf fehlende Einträge
522 | zeigen? Solche Zeiger ins Leere heißen auch ``dangling pointer''. Begründe
523 | deine Antwort:
524 | \fillwithdottedlines{6em}
525 |
526 | \part[1] Wieviele ``Labels'' darf ein Knoten in einer Neo4J-Datenbank haben?
527 | Antwort: \fillin
528 |
529 | \part[1] Wieviele ``Typen'' darf eine Beziehung in einer Neo4J-Datenbank haben?
530 | Antwort: \fillin
531 |
532 |
533 | \part
534 | Wir arbeiten auf einer leeren Neo4J-Datenbank. In die Neo4J-Webkonsole geben
535 | wir folgende \texttt{cypher} Befehle ein:
536 | \begin{lstlisting}
537 | CREATE(romeo:Person {name: 'Romeo'})
538 | CREATE(juliet:Person {name: 'Juliet'})
539 | \end{lstlisting}
540 | Abbildung~\ref{fig:neo4j:graph-merge}~(a) zeigt eine Graph-Visualisierung,
541 | nachdem wir die Befehle ausgeführt haben.
542 | \begin{figure}[h]
543 | \centering
544 | \subfloat[Vor dem \texttt{MERGE}]{\includesvg[inkscapelatex=false, width=0.2\textwidth]{./neo4j/before-merge.svg}}
545 | \qquad
546 | \qquad
547 | \subfloat[Nach dem \texttt{MERGE}]{\includesvg[inkscapelatex=false, width=0.25\textwidth]{./neo4j/after-merge.svg}}
548 | \caption{Offenbar entstehen Duplikate}
549 | \label{fig:neo4j:graph-merge}
550 | \end{figure}
551 |
552 | \newpage
553 | Nun geben wir die folgende \texttt{cypher} Befehle ein:
554 | \begin{lstlisting}
555 | MERGE(:Person {name: 'Romeo'})-[:LOVES]->(:Person {name: 'Juliet'})
556 | \end{lstlisting}
557 |
558 |
559 | Jetzt sieht der Graph wie auf Abbildung~\ref{fig:neo4j:graph-merge}~(b) aus.
560 | \begin{subparts}
561 | \subpart[1]
562 | Wie können die \texttt{cypher} Befehle so verändert werden, dass keine
563 | Duplikate mehr entstehen? Es sollten auch nach mehrmaligen Ausführen der
564 | Befehle keine Duplikate mehr entstehen.
565 | \makeemptybox{14em}
566 | \subpart[2]
567 | Wenn wir initial auf dem Stand von Abbildung~\ref{fig:neo4j:graph-merge}~(a)
568 | \emph{zweimal hintereinander} folgende \texttt{cypher} Befehle ausführen,
569 | wie sieht der Graph dann aus?
570 | \begin{lstlisting}
571 | MATCH(romeo:Person {name: 'Romeo'})
572 | MATCH(juliet:Person {name: 'Juliet'})
573 | CREATE(romeo)-[:LOVES]->(juliet)
574 | \end{lstlisting}
575 | Skizziere den Graphen in der Datenbank:
576 | \makeemptybox{14em}
577 | \end{subparts}
578 | \end{parts}
579 |
580 | \clearpage
581 |
582 | \question VueJS and NuxtJS
583 | \begin{parts}
584 | \part[3]
585 | Zu den Vorteilen von client-seitig gerenderten ``Single-page-applications''
586 | gegenüber traditionellen server-seitig gerenderten Web-Anwendungen gehören
587 | unter anderem:
588 | \begin{checkboxes}
589 | \choice Desktop-ähnliches Nutzererlebnis
590 | \choice Bessere Suchmaschinen-Optimierung
591 | \choice Kompatibilität mit älteren Browsern
592 | \choice Schneller initialer Seitenaufruf (``initial page load'')
593 | \choice Größerer Anteil Nutzdaten in der Kommunikation zwischen Client- und Server
594 | \choice Weniger Last auf dem Server
595 | \end{checkboxes}
596 |
597 | \part[3]
598 | Welche dieser sog.\ ``JavaScript globals'' sollte in Quellcode vermieden werden,
599 | welcher auch von server-seitig vorgerenderten Web-Anwendungen ausgeführt wird:
600 | \begin{checkboxes}
601 | \choice \texttt{console}
602 | \choice \texttt{document}
603 | \choice \texttt{window}
604 | \end{checkboxes}
605 |
606 | \part[1] Zu welcher Art von Fehler kommt es, wenn man trotzdem eines dieser
607 | ``globals'' in einem NodeJS Prozess aufruft?
608 | \fillwithdottedlines{4em}
609 |
610 | \part
611 | Wirf einen Blick auf die Vue-Komponente im Code-Beispiel in
612 | Abbildung~\ref{fig:vue-example}. Wenn in den folgenden Teilaufgaben Änderung
613 | im Quelltext vorgenommen werden sollen, können diese direkt in die Abbildung
614 | eingepflegt werden.
615 | \begin{subparts}
616 | \subpart[1]
617 | Offenbar hat sich ein Fehler eingeschlichen. Eigentlich soll die Methode
618 | \texttt{handleClick} beim Klick auf den Knopf ausgelöst werden. Durch welche
619 | Änderung kann der Fehler behoben werden?
620 | \subpart[1]
621 | Wenn die Methode \texttt{handleClick} aufgerufen wird, welchen Wert hat dann
622 | \texttt{message}?
623 |
624 | Antwort: \fillin
625 | \subpart[2]
626 | Füge ein \texttt{} Feld hinzu, dessen Texteingabe mit dem Zustand
627 | \texttt{message} verknüpft ist. Bei jeder Text-Eingabe soll sich also der
628 | Wert von \texttt{message} verändern.
629 | \subpart[2]
630 | Implementiere eine computed property namens \texttt{exclaimedMessage},
631 | welches \texttt{message} zurückgibt, allerdings mit einem Ausrufezeichen am
632 | Ende.
633 | \subpart[1]
634 | Warum sind computed properties performanter als Methodenaufrufe?
635 | \fillwithdottedlines{8em}
636 | \end{subparts}
637 | \begin{figure}[h]
638 | \centering
639 | \lstinputlisting[
640 | basicstyle=\ttfamily,
641 | numbers=left,
642 | language=HTML
643 | ]{code/vuejs/Example.vue}
644 | \caption{Eine kleine VueJS-Komponente}
645 | \label{fig:vue-example}
646 | \end{figure}
647 | \end{parts}
648 |
649 | \clearpage
650 |
651 | \question Fullstack testing and Requirements Engineering
652 | \begin{parts}
653 | \part[1] Im Kurs haben wir die ``Testing-Pyramide'' und den
654 | ``Testing-Diamanten'' kennengelernt. Beides sind Modelle, die eine
655 | Hilfestellung bieten sollen, um zu einem ausgewogenen Verhältnis der
656 | jeweiligen Test-Klassen zu finden.
657 | Welche Klasse von Tests hat laut dem ``Testing-Diamanten'' den größten Wert
658 | und sollte deshalb besonders oft implementiert werden?
659 |
660 | Antwort: \fillin
661 |
662 | \part[2] Was ist das Alleinstellungsmerkmal von Cucumber Tests?
663 | \begin{choices}
664 | \choice ``Specification by example'', d.h. anstelle abstrakter Dokumentation
665 | wird das Verhalten der Anwendung anhand von Beispielen beschrieben.
666 | \choice ``Executable documentation'', d.h. dadurch dass die Dokumentation
667 | regelmäßig vom Build-Server ausgeführt wird, kann die Dokumentation nicht
668 | mehr veralten (``out-of-date'').
669 | \choice Software-Tests werden in menschliche Sprache übersetzt, sodass auch
670 | Nicht-Programmierer die Tests lesen und nachvollziehen können.
671 | \end{choices}
672 |
673 | \part[2] Die Schablone eine User-Story sieht wie folgt aus:
674 | \begin{lstlisting}
675 | As a
676 | I want to do
677 | In order to
678 | \end{lstlisting}
679 | Diese Schablone soll dazu dienen, dass man bei der Erfassung von Anforderungen
680 | bestimmte Informationen nicht vergisst, z.B. die Zielgruppe und den Grund für
681 | eine gewünschte Funktion. Warum ist es so wichtig, diese Informationen stets
682 | zu dokumentieren?
683 | \fillwithdottedlines{8em}
684 | \end{parts}
685 |
686 | \newpage
687 | \question CSS
688 | \begin{figure}[h]
689 | \centering
690 | \lstinputlisting[
691 | numbers=left,
692 | language=HTML
693 | ]{code/css/example.html}
694 | \caption{Ein beispielhaftes HTML Dokument}
695 | \label{fig:example-html}
696 | \end{figure}
697 | \begin{parts}
698 | \part[3]
699 | Welche HTML-Elemente werden bzw.\ welches HTML-Element wird in Abbildung~\ref{fig:example-html}
700 | mit den folgenden CSS Selektoren selektiert? Gib als Antwort Zeilennummern an:
701 | \begin{subparts}
702 | \subpart
703 | \begin{lstlisting}
704 | .reaction-buttons
705 | \end{lstlisting}
706 |
707 | Antwort: \fillin
708 |
709 | \subpart
710 |
711 | \begin{lstlisting}
712 | .post-footer > .button
713 | \end{lstlisting}
714 |
715 | Antwort: \fillin
716 |
717 | \subpart
718 |
719 | \begin{lstlisting}
720 | .post-footer :first-child
721 | \end{lstlisting}
722 |
723 | Antwort: \fillin
724 | \end{subparts}
725 |
726 | \part[1]
727 | Mit welchen CSS-Selektor können alle Buttons selektiert werden?
728 |
729 | Antwort: \fillin[][2in]
730 |
731 | \end{parts}
732 |
733 |
734 | \question Code Review
735 | \begin{parts}
736 | \part[10] Die folgenden drei Code-Beispiele sind Auszüge aus den Abgaben der
737 | Hausaufgaben und enthalten Schwächen. Finde diese Schwächen und schlage eine
738 | Verbesserung vor. Wenn du eine Schwäche finden kannst und eine sinnvolle
739 | Verbesserung vorschlägst, gibt es dafür einen Punkt.\\
740 |
741 | Über einige dieser Schwächen haben wir ausführlich während der Vorlesung und
742 | während der Übungen und in den Code-Reviews gesprochen. Dazu gehören:
743 | \begin{itemize}
744 | \item
745 | Häufige Ursachen für ``falsch-negative'' oder ``falsch-positive'' Tests,
746 | \item
747 | Sicherheitslücken oder unnötige Preisgabe von empfindlichen Informationen,
748 | \item
749 | häufige Ursachen für Programmfehler, z.~B. vermeidbare Zustände,
750 | \item
751 | Verletzungen von Spezifikationen,
752 | \item
753 | Anti-Patterns in Bezug auf Frameworks.
754 | \end{itemize}
755 | Es gibt einen weiteren Punkt, wenn du erklärst, wie man diese
756 | ``gröberen'' Fehler in Zukunft verhindern kann. Auf der letzten Seite
757 | gibt es genug Platz für Erklärungen.
758 |
759 |
760 | Es spielt keine Rolle, welches Code-Beispiel du dir aussuchst, es werden alle
761 | Verbesserungen und Erklärungen für diese Aufgabe summiert.
762 | \begin{figure}[h]
763 | \lstinputlisting[
764 | basicstyle=\ttfamily,
765 | numbers=left,
766 | numberstyle=\footnotesize,
767 | numbersep=3em,
768 | extendedchars=true,
769 | language=JavaScript
770 | ]{code/review/component-tests/2.js}
771 | \caption{Auszug aus einem VueJS Komponenten Test}
772 | \end{figure}
773 | \begin{figure}[h]
774 | \lstinputlisting[
775 | basicstyle=\ttfamily,
776 | numbers=left,
777 | numberstyle=\footnotesize,
778 | numbersep=3em,
779 | extendedchars=true,
780 | language=JavaScript
781 | ]{code/review/apollo-server/typeDefs.js}
782 | \caption{Die GraphQL Typendefinitionen eines Apollo-Servers. Mit \texttt{token}
783 | ist ein JWT Bearer token gemeint. Das Feld \texttt{password} ist tatsächlich
784 | ein Benutzerpasswort und ist entsprechend sensibel.}
785 | \end{figure}
786 | \begin{figure}[h]
787 | \lstinputlisting[
788 | basicstyle=\ttfamily,
789 | numbers=left,
790 | numberstyle=\footnotesize,
791 | numbersep=3em,
792 | extendedchars=true,
793 | language=JavaScript
794 | ]{code/review/apollo-server/resolvers.js}
795 | \caption{Auszüge aus GraphQL resolver Implementierungen}
796 | \end{figure}
797 |
798 | \clearpage
799 | Hier können Probleme ausführlicher erklärt werden, wenn der Platz neben dem
800 | Code nicht ausreichen sollte. Bitte die Zeilennummer und die Abbildung
801 | angeben, um die Zuordnung zu erleichtern.
802 | \fillwithdottedlines{\stretch{1}}
803 |
804 | \end{parts}
805 |
806 | \end{questions}
807 | \end{document}
808 |
809 | %%% Local Variables:
810 | %%% mode: latex
811 | %%% TeX-master: t
812 | %%% End:
813 |
--------------------------------------------------------------------------------
/archive/Exam/git/initial.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/archive/Exam/neo4j/after-merge.svg:
--------------------------------------------------------------------------------
1 |
2 |
184 |
--------------------------------------------------------------------------------
/archive/Exam/neo4j/before-merge.svg:
--------------------------------------------------------------------------------
1 |
2 |
117 |
--------------------------------------------------------------------------------
/archive/Exam/project-management/software-testing-benefits.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/exercises/1/README.md:
--------------------------------------------------------------------------------
1 | # VueJS
2 |
3 |
4 | Due date: **28.10.2020**
5 |
6 |
7 | ## Goal
8 |
9 | The goal is to reimplement some basic functionalities of [Hackernews](https://news.ycombinator.com/) in VueJS to learn the concepts.
10 |
11 | Hacker News is a social news website focusing on computer science and entrepreneurship. Content can be submitted by users and can be interacted via upvotes or comments. We will focus on the startpage:
12 |
13 |
14 |
15 |
16 |
17 | ### Demo
18 |
19 | This is how the result should look like:
20 |
21 |
22 |
23 |
24 |
25 |
26 | You can use [Vue CLI](https://cli.vuejs.org/) for a quick setup which will setup [single file components](https://vuejs.org/v2/guide/single-file-components.html) for you.
27 |
28 | Note that the official documentation of VueJS does not recommend using `vue-cli` but instead suggests to use a plain [index.html](https://github.com/vuejs/vuejs.org/blob/master/src/v2/examples/vue-20-hello-world/index.html) file.
29 |
30 | Either way is fine, using `vue-cli` is easier but setting up VueJS yourself might be more educational.
31 |
32 | Put your code somewhere in this repository. We suggest a monorepo approch with a folder `webapp` below the repository's root folder.
33 |
34 | ### Objectives
35 |
36 |
37 | Each star gives one point if implemented satisfactorily.
38 |
39 | :star: First of all, push new commits from `main` branch of the [homework repository](https://github.com/Systems-Development-and-Frameworks/homework/) to your team repository.
40 |
41 | Implement a prototype using VueJS which contains:
42 |
43 | :star: A list that renders a number of news items
44 | - The initial list can be hard-coded
45 | - Each item has a `title` and `votes`, the latter are 0 initially.
46 |
47 | :star: Each item has a button to remove itself
48 | - The item should not remove itself from the DOM but tell its parent component to do so.
49 |
50 | :star: Each item has buttons to downvote or upvote itself, respectively
51 | - Each item `$emit('update', item)` the updated item
52 | - The parent component updates the list when an item is updated
53 |
54 | :star: Below the list is a form to add new items to the list
55 | - Prevent the default behaviour of a `