Hello ,
Today I am writing some mistakes we have done for my Event module in GRP
01.All entity should extend a a base class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
@Data @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @JsonIgnoreProperties( value = {"createdAt", "updatedAt"}, allowGetters = true ) public abstract class AbstractEntity { /*Entity ID*/ @Id @GeneratedValue(generator = "UUID") @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator") @Column(nullable = false) private UUID id; /*Audit field*/ @CreatedBy @JsonIgnore @Column(name = "created_by") protected UUID createdBy; @LastModifiedBy @JsonIgnore @Column(name = "last_modified_by") protected UUID lastModifiedBy; @Column(name = "is_deleted") @JsonIgnore private Boolean isDeleted; @Temporal(TemporalType.TIMESTAMP) @Column(name = "created_at", updatable = false) @CreatedDate @JsonIgnore private Date createdAt; @Temporal(TemporalType.TIMESTAMP) @Column(name = "updated_at") @LastModifiedDate @JsonIgnore private Date updatedAt; /*Header field*/ @JsonIgnore @Column(name = "user_id") private UUID userId; @JsonIgnore @Column(name = "employee_id") private UUID employeeId; @JsonIgnore @Column(name = "proxy_user_id") private UUID proxyUserId; @JsonIgnore @Column(name = "org_id") private UUID orgId; @PrePersist protected void onCreate() { updatedAt = createdAt = new Date(); } @PreUpdate protected void onUpdate() { updatedAt = new Date(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
databaseChangeLog: - changeSet: id: 1 author: DDD changes: - createTable: tableName: item_feature_group columns: - column: name: id type: uuid constraints: primaryKey: true nullable: false - column: name: user_id type: uuid - column: name: employee_id type: uuid - column: name: proxy_user_id type: uuid - column: name: org_id type: uuid - column: name: created_at type: timestamp - column: name: updated_at type: timestamp - column: name: is_deleted type: bool constraints: nullable: false value: false #foreignKeyName: fk_party_contact_information #references: contact_information(id) - column: name: created_by type: uuid - column: name: last_modified_by type: uuid - column: name: name type: varchar(500) - addUniqueConstraint: columnNames: name #venue_name, org_id constraintName: item_feature_group_name tableName: item_feature_group - loadData: file: item_feature_group.csv relativeToChangelogFile: true tableName: item_feature_group quotchar: '"' |
02. File should be saved in on table not multiple scattered table. just store the reference of file in one separated Table and refer it by src_entity_id and src_entity
03.Use service layer only and complex logic should come form other helper with pattern like builder ,factory ,facade etc. Maintain Single responsibility in this code though dependency injection (if possible)
04. Must use seed data for database in lequibase .Otherwise I will create more head ace in future development. Seed data should be hard-coded (Must otherwise create confusion)
05. Maintain foreign key constraint with Not null and also follow JPA convention . Never use raw query in project use View in lequibase other wise it will be difficult in refactoring
06. Maintain a consistency in project wise development among team members so that any code or business logic can be reused , refactored and understood clearly . Remember TWO same code is EVIL
05.Use logger with complete logging with in out parameter .So that debugging is easier .
06.Clear domain knowledge and make documentation as more as possible to make effective production grade code.
07. Use reactive form in angular instead of template driven form
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
import {Component, OnInit} from '@angular/core'; import {FormArray, FormBuilder, FormControl, FormGroup, NgForm, Validators} from '@angular/forms'; import {ActivatedRoute} from '@angular/router'; @Component({ selector: 'app-root', template: ` <form (ngSubmit)="submit(f)" [formGroup]='orderForm' class="form-horizontal" #f="ngForm" novalidate> <div class="card border-primary"> <div class="card-header zero-left-margin-padding"> <b>Form Array example</b> </div> <div class="card-body"> <div class="form-group row required form-group-sm" > <label class="col-md-2 col-form-label">CustomerName </label> <div class="col-md-4"> <input class="form-control form-control-sm" type="text" formControlName="customerName" placeholder=" Enter customerName" > </div> </div> <div formArrayName="items" *ngFor="let item of orderForm.get('items').controls; let i = index;"> <div [formGroupName]="i"> <input type="text" formControlName="name" placeholder="Enter remark" [ngClass]="{ 'is-invalid': orderForm.controls.items.controls[i].controls.name.touched && orderForm.controls.items.controls[i].controls.name.invalid }" > <div class="badge badge-danger" *ngIf="orderForm.controls.items.controls[i].controls.name.touched && orderForm.controls.items.controls[i].controls.name.invalid"> Name is required and must be greater than three character </div> <input formControlName="description" placeholder="Item description"> <input formControlName="price" placeholder="Item price"> <button *ngIf="orderForm.controls.items.controls.length > 1" (click)="deleteRow(i)" class="btn btn-danger">Delete Button</button> </div> </div> <div> <button class="btn btn-pill btn-outline-success customBtn" type="button" tooltip="add" (click)="addItem()" > Add item </button> </div> </div> <div class="card-footer card-footer-sm" > <button type="submit" class="btn btn-success pull-right"><i class="fa fa-save"></i> Save </button> <a class="btn btn-warning pull-left"> <i class="fa fa-arrow-circle-left"></i> Back</a> </div> </div> </form> `, }) export class AppComponent implements OnInit { title = 'form-array'; orderForm: FormGroup; // items: FormArray; constructor( private formBuilder: FormBuilder ) { } createItem(): FormGroup { return this.formBuilder.group({ name: [null, Validators.required], description: '', price: '' }); } ngOnInit() { this.orderForm = this.formBuilder.group({ customerName: '', items: this.formBuilder.array([]) }); const item: any = {}; item.name = 'akash'; item.price = 10; item.description = 'lol'; (this.orderForm.get('items') as FormArray).push(this.createItem()); (this.orderForm.get('items') as FormArray).at(0).patchValue(item); } addItem(): void { if (this.orderForm.valid) { (this.orderForm.get('items') as FormArray).push(this.createItem()); } else { this.validateAllFields(this.orderForm); } } deleteRow(index: number) { // control refers to your formarray const control = <FormArray>this.orderForm.controls['items']; // remove the chosen row control.removeAt(index); } submit(ngForm: NgForm) { console.log(this.orderForm.value); if (this.orderForm.valid) { // console.log(this.orderForm.value); } else { this.validateAllFields(this.orderForm); } } validateAllFields(formGroup: FormGroup) { Object.keys(formGroup.controls).forEach(field => { const control = formGroup.get(field); if (control instanceof FormControl) { control.markAsTouched({ onlySelf: true }); } else if (control instanceof FormGroup) { this.validateAllFields(control); } }); } } |
08.Helper will not contain any logic in angular 6.
09.Use a architecture .(Hexagonal) and make consistency along with project.Use same operation for all the CRUD and complex logic operation
10.Put logic in controller specially the business operation. Use Service for dependency.
11.A row should be updated on a service method and complex processing use pattern as helper and reuse it possibe
12.Always use DTO / ViewModel for all logic .
13.Use constructor injection for testing .
14.Write unit test(moqito and junit) and api integration test(mokmvc)
15.A line should be one responsibility dont use
return iservice.getMeThis();
instead
var testObject = iservice.getMeThis();
return testObejct;