<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vesin Dusko</title>
    <description>The latest articles on DEV Community by Vesin Dusko (@vesindusko).</description>
    <link>https://dev.to/vesindusko</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F744356%2Fc17e15cf-a5aa-4986-bff4-f28f64453510.jpg</url>
      <title>DEV Community: Vesin Dusko</title>
      <link>https://dev.to/vesindusko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vesindusko"/>
    <language>en</language>
    <item>
      <title>Upgrade to Angular13 and Spring boot 2.6.1</title>
      <dc:creator>Vesin Dusko</dc:creator>
      <pubDate>Mon, 06 Dec 2021 12:13:40 +0000</pubDate>
      <link>https://dev.to/vesindusko/upgrade-to-angular13-and-spring-boot-261-4a56</link>
      <guid>https://dev.to/vesindusko/upgrade-to-angular13-and-spring-boot-261-4a56</guid>
      <description>&lt;p&gt;In the last few weeks, we have been busy migrating our product to #angular 13 and #springboot 2.6.1.&lt;/p&gt;

&lt;p&gt;I can't share with you our product code, so we also upgrade our &lt;a href="https://github.com/alchemycloud/todo"&gt;TODO&lt;/a&gt; and &lt;a href="https://github.com/alchemycloud/petclinic"&gt;PetClinic&lt;/a&gt; apps.&lt;/p&gt;

&lt;p&gt;Check it out!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>java</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Code owners and review in GitHub</title>
      <dc:creator>Vesin Dusko</dc:creator>
      <pubDate>Wed, 10 Nov 2021 11:07:11 +0000</pubDate>
      <link>https://dev.to/vesindusko/code-owners-and-review-in-github-31lk</link>
      <guid>https://dev.to/vesindusko/code-owners-and-review-in-github-31lk</guid>
      <description>&lt;p&gt;Code review is one of the standards for good code quality and knowledge sharing inside teams. During my carrier, I have seen a lot of different setups, and some of them are better than others.&lt;/p&gt;

&lt;p&gt;We are using GithHub PRs as a moment for quality control. It allows us to establish rules when a code from a working branch can be merged with the development branch. &lt;/p&gt;

&lt;p&gt;One of the basic rules is code review. All PRs have this type of protection. At least one member of the architect team should give its approval and at least two other developers. &lt;/p&gt;

&lt;p&gt;The other gate is that at least one of the code owners of changed files should also do a code review. The concept of code owners is not a well-known functionality of GitHub, but we found it very powerful and valuable. &lt;/p&gt;

&lt;p&gt;Details about this functionality you can find on &lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners"&gt;GitHub&lt;/a&gt; and examples you can see at &lt;a href="https://github.com/alchemycloud/todo/blob/master/CODEOWNERS"&gt;todo example&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Y3R34nr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnagfauhb3gvrema7r11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Y3R34nr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnagfauhb3gvrema7r11.png" alt="Example" width="704" height="288"&gt;&lt;/a&gt;&lt;br&gt;
No alt text provided for this image&lt;br&gt;
The good thing about code owners is that any file or folder in the code can have different owners or GitHub groups, and by it, you can make sure that the right people have done code reviews.&lt;/p&gt;

&lt;p&gt;Also, in the case of the larger PRs, the reviewer can adjust the filter to see only files you are responsible for, speeding up the review process.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fbtDm8FE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x7n4z1m9x9lve0ybauq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fbtDm8FE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2x7n4z1m9x9lve0ybauq.png" alt="Filter" width="616" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>codereview</category>
      <category>productivity</category>
    </item>
    <item>
      <title>SpringBoot and Angular PetClinic app </title>
      <dc:creator>Vesin Dusko</dc:creator>
      <pubDate>Tue, 09 Nov 2021 07:40:36 +0000</pubDate>
      <link>https://dev.to/vesindusko/springboot-and-angular-petclinic-app-2ec9</link>
      <guid>https://dev.to/vesindusko/springboot-and-angular-petclinic-app-2ec9</guid>
      <description>&lt;p&gt;We are continuing with  #sharing some of our internal knowledge with you guys. For example, as another test project for our Sifu generator, we specified a PetClinic app. The entire app specification is 470 lines of code ( check for petclinic.sifu file).&lt;br&gt;
It is two Angular clients with a SpringBoot backend.&lt;/p&gt;

&lt;p&gt;Check it out and, tell me what you would do differently?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alchemycloud/petclinic"&gt;PetClinic repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>tutorial</category>
      <category>angular</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Query counter for Hibernate
</title>
      <dc:creator>Vesin Dusko</dc:creator>
      <pubDate>Mon, 08 Nov 2021 11:59:21 +0000</pubDate>
      <link>https://dev.to/vesindusko/query-counter-for-hibernate-1h7m</link>
      <guid>https://dev.to/vesindusko/query-counter-for-hibernate-1h7m</guid>
      <description>&lt;p&gt;Hibernate is the most used ORM framework by Java developers, but there are still many misunderstandings about how it works and its best practices.&lt;/p&gt;

&lt;p&gt;ORM provides great abstraction between objects and DB, and that is also the problem. Developers tend to forget that queries are expensive and that accessing DB like accessing common objects in memory creates an unpredictable number of DB queries.&lt;/p&gt;

&lt;p&gt;One of the ways to prevent it from happening is to monitor queries that a code creates, and it is a tricky thing to do. You can set the level of Hibernate login to log DB calls and track it like that. The problem with that solution is that it is implicit, not part of the code, and you need to do it manually.&lt;/p&gt;

&lt;p&gt;A more elegant solution is to create an interceptor (&lt;a href="https://github.com/alchemycloud/todo/blob/master/backend/src/main/java/com/todo/backend/interceptor/QueryCountInterceptor.java" rel="noopener noreferrer"&gt;QueryCountInterceptor&lt;/a&gt;) and thread-local variable (like &lt;a href="https://github.com/alchemycloud/todo/blob/master/backend/src/main/java/com/todo/backend/util/AppThreadLocals.java" rel="noopener noreferrer"&gt;AppThread&lt;/a&gt;) that will intercept hibernate prepare statements and process them. QueryCountInterceptor is great for code debugging. It is also a learning tool for newcomers into Hibernate. Besides that, it can be integrated with tests. For example, after each tested method, assert the number of queries that have been performed. In this way, you can avoid the situation that a code change unexpectedly changes method performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbip900a36zupp7uvjt2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbip900a36zupp7uvjt2.png" alt="QueryCounter.java"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>hibernate</category>
      <category>orm</category>
      <category>queries</category>
    </item>
    <item>
      <title>Specification as Code, the full power of #DRY and #model-driven development</title>
      <dc:creator>Vesin Dusko</dc:creator>
      <pubDate>Fri, 05 Nov 2021 11:03:01 +0000</pubDate>
      <link>https://dev.to/vesindusko/specification-as-code-the-full-power-of-dry-and-model-driven-development-4280</link>
      <guid>https://dev.to/vesindusko/specification-as-code-the-full-power-of-dry-and-model-driven-development-4280</guid>
      <description>&lt;p&gt;We have built our ToDo app (backend, frontend) using code generators and domain-specific language. Now we can analyze the benefits of MDD (model-driven development).&lt;/p&gt;

&lt;h1&gt;
  
  
  Speed
&lt;/h1&gt;

&lt;p&gt;Writing the entire todo app in todo.sifu took us half an hour, and we got much code generated in 2-3s, 256 files, and 15k lines of code!&lt;/p&gt;

&lt;h1&gt;
  
  
  Consistency
&lt;/h1&gt;

&lt;p&gt;All the code is 'same,' implemented in the same way with the same coding rules. It is like the same developer wrote it.&lt;br&gt;
Solution #overview - We can see the entire app overview in one file todo.sifu file. We can say that sifu spec is 'documentation as code', which is the essence of DRY. We don't duplicate the knowledge. All the information from sifu spec goes directly into the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every piece of knowledge must have a single, unambiguous, authoritative representation within a system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Maintainability
&lt;/h1&gt;

&lt;p&gt;Reading, updating, and refactoring the app are much more manageable. The impact of every change is much more visible on such a high level. For example, we can see how many APIs will require updating by changing some models or queries.&lt;/p&gt;

&lt;h1&gt;
  
  
  Modeling
&lt;/h1&gt;

&lt;p&gt;Instead of thinking about the implementation, developers are more focused on the modeling. Our experience is that sometimes we spend hours or days modeling and rewriting the sifu file with multiple iterations before generating code and diving into implementation. We are detecting flaws and fixing them 100x times faster than in the traditional development way.&lt;br&gt;
Best #practices - Because of the code generator, the best practices will be enforced into the code. APIs will be implemented in the same way, all controllers, repositories, models, the security part of the app, web components, routings.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quality
&lt;/h1&gt;

&lt;p&gt;Thanks to the code generator, many dummy mistakes that can occur during implementation are avoided. Even if the generator has a bug and generates code with a bug, when the generator is fixed, all of them will be fixed by the next regeneration. We are solving problems in one place and distributing solutions into the entire code base. In our case, almost 80% of the application code is generated, and we don't test that code. That gives us great confidence and lets us focus on other things.&lt;/p&gt;

&lt;h1&gt;
  
  
  Upgrading
&lt;/h1&gt;

&lt;p&gt;For example, these days, Angular 13 is released. To successfully upgrade an app to the new version, developers need to go through a set of steps. Update libraries, use the latest features of the framework, refactor some parts of the code, maybe even change the entire architecture. And repeat the same process for every client that the app has. There is much manual work to be performed to complete this job successfully. In the case of code generators, we need to update the code generator, which is no small amount of work, and then regenerate. All the parts of the code will get the same treatment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Validation
&lt;/h1&gt;

&lt;p&gt;One of the most significant benefits is the validation of the specification. Because the specification is a code, we can compile it and perform all different types of validations. This benefit is even more potent in the case of enterprise apps. For example, our app has 30k lines of specification code.&lt;/p&gt;

&lt;p&gt;To use MDD, you need to invest time and resources into building the toolings, but the benefits are colossal. We at alchemy can develop a codeless platform with millions of lines of code and rewrite it already three times from scratch with the development team of 10-15 members!&lt;/p&gt;

&lt;p&gt;In my previous life (the one without MDD and Sifu language and the code generator), for the same achievement, it would take a team of at least 75, and success would be much more uncertain.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>codequality</category>
      <category>writing</category>
    </item>
    <item>
      <title>ToDo app with Sifu code generator</title>
      <dc:creator>Vesin Dusko</dc:creator>
      <pubDate>Thu, 04 Nov 2021 07:56:34 +0000</pubDate>
      <link>https://dev.to/vesindusko/todo-app-with-sifu-code-generator-179a</link>
      <guid>https://dev.to/vesindusko/todo-app-with-sifu-code-generator-179a</guid>
      <description>&lt;p&gt;As part of promoting DRY (don't repeat yourself), MDD (model-driven development), and code generator, I would like to show its full power on a real-life example.&lt;/p&gt;

&lt;p&gt;We will implement a simple ToDo app with backend and client app. Let's start.&lt;/p&gt;

&lt;h2&gt;
  
  
  ToDo project
&lt;/h2&gt;

&lt;p&gt;First we will define the project with basic informations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;todo project[
    url www.todo.com 
    namespace com.todo
    version 1 . 0 . 0 . 0
    environments prod
    developer(duskovesin)
]( 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;Now we will define the #backendpart of the app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend server[
        owners(duskovesin)
        template springboot(tests fabut)        
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are starting with the definition of User and Todo #models, with a few fields and Todo Status #enums.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        UserRole enum(
            ADMIN
            MEMBER
        )

        Status enum(
            NOT_STARTED
            IN_PROGRESS
            DONE
        )

        User model(
            firstName text[min 1, max 40, searchable]
            lastName text[min 1, max 60]
        )

        Todo model(
            user User
            task text[min 1, max 255]
            date date
            status Status
        )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to specify the type of security that we want to use in the app, in this case, we are using role-based security on top of the User model with #username and #password as security #authentication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        security(
            principal User
            role UserRole
            type username
        )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can focus on APIs. We will create two sets of #REST APIs. &lt;/p&gt;

&lt;h4&gt;
  
  
  UserApi
&lt;/h4&gt;

&lt;p&gt;UserApi will have #CRUD API endpoints for manipulation with users in the system, that can be accessed only by ADMIN users, users endpoint to access to all users in the system, and one that Admin can use to check other users Todos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UserApi api(

            user crud[model User, rest, secured ADMIN]

            users read[
                select from User
                rest
                secured ADMIN
            ]

            userTodos read[
                select from Todo
                     where Todo.user == user
                     orderable by Todo.task
                rest
                secured ADMIN
            ]
        )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  TodoApi
&lt;/h4&gt;

&lt;p&gt;TodoApi with CRUD endpoints for users to be able to create ToDo and userTodos endpoint that will be used by any users to access ti his own ToDos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        TodoApi api(

            todo crud[model Todo, rest]

            todos read[
                select from Todo
                     join User on Todo.user
                response list dto(
                    Todo.id
                    userUsername User.username
                    Todo.task
                    Todo.date
                    Todo.status
                )
                rest
                secured(ADMIN, MEMBER)
            ]
        )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On average, for developers to implement all controllers, APIs, DTOs, models, enums and repositories, db-changelogs and all other parts of sping boot infrastructure code would take at least a few days...&lt;/p&gt;

&lt;h3&gt;
  
  
  WebApp
&lt;/h3&gt;

&lt;p&gt;Now lets move to the client part of the app.&lt;/p&gt;

&lt;p&gt;First, let's define the client app and specify which type of applications it will be generated to. Also, we will define, to which backend it will be connected. Also, we will define the application path and which page is the home page for admin and member users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webapp client[
        owners(duskovesin)
        connectedTo backend
        template angular
        path /webportal
        home todosPage(ADMIN, MEMBER)
    ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we need to create two pages, one for users to organize their ToDos and the other one for admins to administrate with users.&lt;/p&gt;

&lt;h4&gt;
  
  
  ToDo page
&lt;/h4&gt;

&lt;p&gt;ToDo page will have a list of user todos, add a button for creating new todo, edit button for opening edit form and delete button for todo deletions. All components will be connected with appropriate API calls which can be seen in the spec.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        todosPage page[
            path /todos
            secured(ADMIN, MEMBER)
        ](
            addTodo button {
                on click open createTodo(none) {
                    on closed do todos.load
                }
            }
            todos table[
                load TodoApi.todos
            ](
                editTodo button {
                    on click open editTodo(item.id)
                }
                deleteTodo button {
                    on click open deleteTodo(item.id)
                }
            )
        )

        createTodo form[
            submit TodoApi.createTodo
        ] {
            on success close
        }

        editTodo form[
            load TodoApi.readTodo
            submit TodoApi.updateTodo
        ] {
            on success close
        }

        deleteTodo form[
            load TodoApi.readTodo
            submit TodoApi.deleteTodo
        ] {
            on success close
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Users page
&lt;/h4&gt;

&lt;p&gt;The users page will be organized in the same way, with a small difference that the admin user will be able to access the ToDos of the other users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        usersPage page[
            path /users
            secured ADMIN
        ](
            addUser button {
                on click open createUser(none) {
                    on closed do users.load
                }
            }
            users table[
                load UserApi.users
            ](
                viewUserTodos button {
                    on click fire ViewTodos(item.id)
                }
                editUser button {
                    on click open editUser(item.id)
                }
                deleteUser button {
                    on click open deleteUser(item.id)
                }
            ) {
                ViewTodos event(id integer)
                external {
                    on ViewTodos do userTodos.reload(event.id, none, none)
                }
            }
            userTodos table[
                input(*, *, *)
                load UserApi.userTodos
            ]
        )

        createUser form[
            submit UserApi.createUser
        ] {
            on success close
        }

        editUser form[
            load UserApi.readUser
            submit UserApi.updateUser
        ] {
            on success close
        }

        deleteUser form[
            load UserApi.readUser
            submit UserApi.deleteUser
        ] {
            on success close
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Security page with sign-in form is automatically generated according to the best practices.&lt;/p&gt;

&lt;p&gt;The amount of code that's necessary to write to do this basic implementation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Java                           148           2056             93           9193
TypeScript                      45            660            113           3083
HTML                            19              1              0           1114
XML                             14              0              4            881
JSON                             9              0              0            654
Maven                            3              0              4            246
Sass                            11             44             12            152
YAML                             3              2              0            102
JavaScript                       2              3              4             61
Markdown                         2             13              0             16
-------------------------------------------------------------------------------
SUM:                           256           2779            230          15502
------------------------------------------------------------------------------------


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to code generator sifu we are able to implement it in under 30 minutes...&lt;/p&gt;

&lt;p&gt;You can check the &lt;a href="https://github.com/alchemycloud/todo"&gt;code on github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>java</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
