My last weeks were super busy. As a result, I had to neglect my
code-confident challenge and was feeling sad about it. I knew already knew for longer what my next practice project should be about: extending an existing backend feature. I found, however, that getting it started was a lot more difficult than I expected. When I finally could start, I got intrigued yet realized I need to learn a lot more. In the end, I did the biggest part just on one day as I couldn't let go anymore!
April 27
May 12
May 13
May 14
- pairing session with Amitai Schleier
- presented him my current problem, first lack of time and now stuck in researching projects trying to decide which one to work on
- told him about my criteria and desired tech stack
- started to present my latest list of 5 candidates
- Amitai: likes to look at tests first to see if they are readable and to see what the app is supposed to be doing
- after the first project he stopped me and suggested a project he just found by using Duck Duck Go search "open source spring-based application": Pet Clinic, a Spring demo project
https://github.com/spring-projects/spring-petclinic
http://projects.spring.io/spring-petclinic/
- cloned the project
- Amitai: let's try to run it first
- ran it using the run configuration detected by IntelliJ; ran but did not find css
- the readme showed how to run the app --> worked this time including building of css
./mvnw package
java -jar target/*.jar
- wanted to use IntelliJ and make it faster, found we could add the package step as Maven goal step before launch: "package"; tried out different variants, found we needed to keep the build step before
- discussed general approach to tackle an existing app; I shared it depends what I am looking for, if I'm reviewing other people's code or if I'd like to contribute myself, etc.; Amitai: wants to see if he can quickly get something to change, see the cause and effect; he could read a lot and model and everything but rather prefers changing something as better test of understanding; wrote a tweet thread about cause & effect
- we decided to change the pet picture on the welcome page to a different one; used this as valid reason to google for cute animal pictures ^^; replaced the image, replaced the image reference, verified the change got applied after application restart
- before going further, we felt that packaging took too long as it was running all tests; wanted to comment them out, but could not find them in the pom; looked upMaven lifecycle (https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) and found that tests are included by default; found we can skip them by calling "package -Dmaven.test.skip=true"; startup now a lot faster, still a bit slow for actual fast feedback during development, yet doable
- had a look at what the app already provided, like "find owner"; decided to add "find pets"
- added a new menu item (copy & paste from find owners), restarted - nice, we land on the error page as expected
- added a controller, copied over from owners; copied the owners html page, adapted as well; our "hopothesis" would have been that now we would be able to access a find pets page with a form to search for owners; yet we knew we probably missed something and indeed, we got the error page instead
- we realized the relationship of owners and pets was not modeled parallel as assumed, but having pets subordinate to owners
- Retrospective:
- Lisi: thank you so much, you got me unstuck in a few minutes! Amitai: seems like my super power, as I have to always get myself unstuck: I know how to orient myself in my problem space, and know how to help people orient themselves in their problem spaces
- Amitai stayed in the navigator role, Lisi as driver; both thought it went well, were not sure if it was okay for the other one but only addressed it in the end; Amitai: felt you picked up things, needed to instruct less and less, you already knew what I wanted; Lisi: when I want to learn, I try to keep myself on the driver seat; I also learn a lot as navigator, having to express my intent and decide where to go next, yet now it's about hands-on practice; Amitai: agree, it's always good to practice; agreed to switch roles next time
- learned that copy & paste is not always working, we have to learn more; was a good reminder to think about the model and how we would want it to be; having pets subordinate to owners did not feel right; what if a pet changes the owner? We would not want to loose the record for the pet, or the past owners; also from a moral standpoint a partnership would be better
- I will have to decide where to go next and define my scope for this practice project; Amitai: Gilded Rose is known as refactoring kata, but he likes to call it the "when to stop" kata; what's the cheapest thing you can do? It's about business, not about the cleanest code; it's really important to zoom out, zoom back in, zoom out again, and realize when to stop
- Lisi: last session and this one as well I gained a lot of benefit from what you shared, bits and pieces of knowledge here and there, and especially from your approaches, how to tackle things; they work well for the concrete thing, but are also applicable in a generic way, will also help me later
- Amitai: last time you gave me energy, happy to give it back this time!
- agreed to do a third session end of June / July
- TODO:
- set up practice project
- define scope
- do it
May 15
May 16
- tried to understand app better
- need debugging to understand more
- not much time today
May 18
- debugging the owner controller: did not stop in debugger - why? still haven't found out; would be something to investigate in a pairing session
- learned more about the demo project; https://projects.spring.io/spring-petclinic/ provided lots of info, however, for an outdated version
- found the community built a lot more versions: https://github.com/spring-petclinic among them also one for Angular :) https://github.com/spring-petclinic/spring-petclinic-angular (could be the perfect target for my next challenge!)
- learned more about MVC (Model View Controller): https://spring.io/guides/gs/serving-web-content/
- saw our get mapping is a bit different, realized I need to look that up and learn more
- learned more about Thymeleaf inputs https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#inputs
- trying to adjust controller to have correct result collection for binding, adding results from search by first name to the results from search by last name https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#addAll-java.util.Collection-; assumed the resulting collection will contain duplicates --> assumption was correct! keeping fields empty to get full list is now showing duplicates; also, existing first name is still showing full list
- https://www.geeksforgeeks.org/how-to-remove-duplicates-from-arraylist-in-java/ tried the Stream version and found it cannot be cast to a collection
- used set instead of collection and it works! bye bye duplicates :)
- found that when I provide values for both fields, search by first name does work now indeed! --> found I always list all in case one field is empty... o_O changed this to only show all in case both are empty --> still, one empty field will show the list of all owners
- cases:
- last name empty, first name empty => list all owners
- last name exists once, first name empty => show owner details (does not work yet)
- last name empty, first name exists once => show owner details (does not work yet)
- last name exists multiple times, first name empty => list selection of owners (does not work yet)
- last name empty, first name exists multiple times => list selection of owners (does not work yet)
- last name does not exist, first name exists once => show owner not found (does not work yet)
- last name exists once, first name does not exist => show owner not found (does not work yet)
- last name does not exist, first name exists multiple times => show owner not found (does not work yet)
- last name exists multiple times , first name does not exist => show owner not found (does not work yet)
- last name does not exist, first name does not exist => show owner not found
- last name empty, first name does not exist => show owner not found (does not work yet)
- last name does not exist, first name empty => show owner not found (does not work yet)
- ...
- more cases:
- both names exist, but for different records => show owner not found (now shows both records)
- parameterless GET request /owners should still list all
- feel the database query should already take care of filtering everything; implemented look up by full name for results list --> oh my it works!!
- what about exact same full name, but different entries? should still list both entries --> and it does!
- not flawless but worth to commit it :D
- added tests for new controller feature; test for not existing first name fails, not sure why yet --> experimenting made me finally understand better what the "rejectValue" method does in the controller! added handling in case first name is not found; now error message is displayed twice! ^^
- researched a lot more regarding Thymeleaf and error messages
https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#validation-and-error-messages
https://stackoverflow.com/questions/50005969/thymeleaf-or-operator-in-thif?rq=1
https://spring.io/guides/gs/validating-form-input/
https://teamtreehouse.com/community/where-does-thymeleaf-get-the-error-messages-from
https://howtodoinjava.com/spring-mvc/spring-mvc-display-validate-and-submit-form-example/
- found how to display an error for a specific field:
<p th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">Error</p>
- however, wanted to have a combined message if an owner is not found, not separated per field; found how to add and display global error:
- Controller:
result.reject("ownerNotFound", "not found");
- Template:
<p th:if="${#fields.hasGlobalErrors()}" th:each="err : ${#fields.globalErrors()}" th:text="${err}">Global Errors</p>
- downside: the test for the global error is super generic, did not find a way to test for exact error
https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html
https://blog.codeleak.pl/2014/08/spring-mvc-test-assert-given-model-attribute-global-errors.html
- tested the tests, made them fail, added assertions; how to assert at least for the number of results found? haven't found an answer yet
- still, the scope of this challenge is fulfilled for now, I implemented a small new feature :D can still extend it, improve it further and clarify the open questions when pairing with others
No comments:
Post a Comment