lundi 22 mars 2021

Redux/Ngrx state/reducer design for handling state with dynamic fields that may not exist unless initialized

The details below rely on pseudo code, so please don't assume they're syntactically/sematnically correct Redux/JavaScript/NgRx. My question is a design question rather than implementation specific.

{
  reports: {
    companyAlpha: {
      ...
    },
    companyBeta: {
      ...
    },
  },
}

Suppose I have a state like this, reports contains a 'map' of company object. The keys in reports are dynamic and can't be assumed to exist. I'm getting the exigence using some other means, doesn't matter for my question.

My question is what's the right design pattern here for handling this sort of dynamic state?

Because the issue comes down to the reducers mainly. Because we have to initialize the report entry,

case INIT_REPORT:
  return {
    ...state,
    reports: {
      // add a new entry in reports based on new action
    }
  }

So that means when we have to perform some action like updating a field inside a report,

case UPDATE_REPORT_VALUE_X:
  // first have to check if the report eixsts
  const report = state.reports[action.reportId] // here `action.reportId` is like `companyAlpha` etc.

  if (!report) { return state; } // we can't update because it's not initialized!

  return {
    ...state,
    reports: {
      ...state.reports,
      [action.reportId]: {
        ... // update it however
      }
    }
  }

But now we have to do the if check before we perform an update to see if the report is initialized otherwise the action can't proceed.

Is there a better way to do this so you make 'impossible-states-impossible' (here make it impossible to perform a UPDATE_REPORT_VALUE_X before INIT? Given a state machine, all the further states should be inaccessible unless you've reached the INITIALIZED state from the UNINITIALIZED initial state.

For example, a possible state machine,

  (UNINITIALIZED)
        |
        |
    action: INIT
        |
        v
   (INITIALIZED)
        |
        |------ action: UPDATE_REPORT_VALUE_X ---> (STATE_A)
        |------ action: UPDATE_REPORT_VALUE_Y ---> (STATE_B)
        |------ action: UPDATE_REPORT_VALUE_Z ---> (STATE_c)

Is it possible to do something like this? Enforce INIT before UPDATE_REPORT_VALUE_X is a possible action?

Again the big concern is that if we're not initialized, every single reducer will need to do a is-initialized check making each reducer 2x as complex as it needs to be (two branch paths)

An analogous(?) design in functional programming is that of a monadic Result/Maybe type. If a value is Error/None you can still perform actions along the 'good' path without having to do a if check in each stage of the pipeline. This enables the functions at each stage to avoid the 2x complexity they otherwise would suffer from if you didn't make use of a Result/Maybe (monadic) type.

(forgive me if I used 'monadic' incorrectly here)

Should I create a separate table in DB for UserAddress helper class Java, Hibernate, Postgres?

I am making a small restful service for user management. By assignment, the User is defined by the following values:

◦ First name 
◦ Last name 
◦ Date of birth 
◦ Login 
◦ Password 
◦ Input field “About me” 
◦ Address of residence (country, city, street, house, flat)

When designing, I paid attention to the address and thought that it would be wrong to write everything together in one address field and make a similar attribute in the database table, because then different filtering by addresses would become very inconvenient. Then I delimited the address field into 5 fields (those in brackets). However, having done so, I realized that my class, given the id field, has 13 fields, what, in my understanding, makes the class too overloaded and "wrong". Then I decided to make a separate class for the address and use it as a field for the user, namely:

@Entity
public class UserAddress {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;
    private String country;
    private String city;
    private String street;
    private int house;
    private int flat;

}

And having done so, I'm not entirely sure how to proceed, as a result of which I have the following questions:

  1. Should I move 5 address fields into a separate class in UserAddres?
  2. If so, is it worth to make this class Entity and creating table in the database for it?
  3. Should I consider it like a complete class (create getters / setters, equals and hashcode, service layer)?
  4. Will filtering users by address become even more complicated than it was originally?
  5. What is the best way to deal with such a situation?

Having trouble implementing my first Decorator pattern

I have a simple app that takes a string and returns the number of unique characters in the string. It is expected that a string may be passed several times to the method. The method should cache the results, so that when the method is given a string previously encountered, it will retrieve the stored result.

For learning purposes I need to implement caching using decorator pattern. What I learned from the web:

  1. First I create an interface
public interface CharCount {
                Map<String, Long> charCount(String input);
        }
  1. It's simple implementation - without caching
public class CharCountImplement {

    Map<String, Long> charCount(String input) {
        return Arrays.stream(input.split(""))
                .collect(Collectors.groupingBy(Function.identity(), HashMap::new, Collectors.counting()));
    }
}
  1. Decorator class
public abstract class Decorator implements CharCount {
    private CharCount charCount;

    @Override
    public Map<String, Long> charCount(String input) {
        return charCount.charCount(input);
    }
}
  1. Now I must create the concrete decorator, but I can't quite figure it out
public class CachedDecorator extends Decorator {

    // decorator must contain something else

    public Map<String, Long> charCount(String input) {
        // some decoration code - no problem with it
        return super.charCount(input);
    }

}

I don't quite catch the principle of this design pattern, and how to use it in my case. I have watched/read numerous tutorials for pizza and coffee decorators, did not help.

Vert.x event bus performance issue (design problem)

I am still getting familiar with vert.x. Coming from Spring boot and Spring webflux background, I wanted to try out some basic stuffs that I used to do in Spring eco-system.

So my idea was writing an api exposed via a controller, which will delegate the actual work to a service . The only way I could think of achieving this in vert.x world was via utilizing event-bus. Here, my KeyValueServiceVerticle's getKeyValues method is supposed to fetch list of key-values from a publisher (keyValueRepository.findAllItems().items()) and send them back via event-bus to the original event publisher api. I am indeed getting the result (list of key-values) as expected but somehow I am not satisfied with the performance. I put some load in equivalent code of spring webflux and vert.x and my webflux implementation always performs better (higher RPS). Related repository: https://github.com/tahniat-ashraf/spring-boot-webflux-vert.x-comparison

Am I blocking the code somewhere? Is there a better vert.x way to achieve what I am trying to achieve?

Related code:

public class KeyValueController extends AbstractVerticle {

  @Override
  public void start() throws Exception {
    Router router = Router.router(vertx);
    router
      .route()
      .handler(BodyHandler.create());
    router.route()
      .handler(LoggerHandler.create(LoggerFormat.DEFAULT));
    router
      .route(HttpMethod.GET, "/keyValues")
      .handler(this::getKeyValues);

    vertx
      .createHttpServer()
      .requestHandler(router)
      .listen(6678);
  }

  private void getKeyValues(RoutingContext routingContext) {
    vertx
      .eventBus()
      .request(KeyValueServiceVerticle.GET_LIST_ADDRESS, new JsonObject(), messageAsyncResult ->
        routingContext.response()
          .putHeader("content-type", "application/json")
          .end((String) messageAsyncResult.result().body())
      );
  }
}

and

public class KeyValueServiceVerticle extends AbstractVerticle {

  public static final String GET_LIST_ADDRESS = "GET_LIST_KEY_VAL";
  private KeyValueRepository keyValueRepository;
  private DynamoConfiguration dynamoConfiguration;

  @Override
  public void start() throws Exception {
    dynamoConfiguration = new DynamoConfiguration();
    keyValueRepository = new KeyValueRepository("dev-paybill-key-value", dynamoConfiguration.getDynamoDBEnhancedClient());
    var eventBus = vertx.eventBus();
    eventBus
      .consumer(KeyValueServiceVerticle.GET_LIST_ADDRESS, this::getKeyValues);

  }

  private <T> void getKeyValues(Message<T> tMessage) {

    Observable.fromPublisher(keyValueRepository.findAllItems().items())
      .toList()
      .subscribe(tList -> {
        JsonArray jsonArray=new JsonArray(tList);
        tMessage.reply(jsonArray.encodePrettily());
      });
  }
}

dimanche 21 mars 2021

design pattern for undoing after I have commited the changes

We can undo an action using Command or Memento pattern.

If we are using kafka then we can replay the stream in reverse order to go back to the previous state.

For example, Google docs/sheet etc. also has version history.

in case of pcpartpicker, it looks like the following:

enter image description here

For being safe, I want to commit everything but want to go back to the previous state if needed.

I know we can disable auto-commit and use Transaction Control Language (COMMIT, ROLLBACK, SAVEPOINT). But I am talking about undoing even after I have commited the change.

How can I do That?

How do i do this question regarding 2d arrays and patterns , Java

Question

Im honestly just stumped at this question.

Strategy design pattern Example?

Following is stretagy design pattern example take from here. First of all we will create the interface for our strategy, in our case to pay the amount passed as argument.

public interface PaymentStrategy {
 
    public void pay(int amount);
}

public class CreditCardStrategy implements PaymentStrategy {
 
    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;
 
    public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate){
        this.name=nm;
        this.cardNumber=ccNum;
        this.cvv=cvv;
        this.dateOfExpiry=expiryDate;
    }
    @Override
    public void pay(int amount) {
        System.out.println(amount +" paid with credit/debit card");
    }
 
}



 public class PaypalStrategy implements PaymentStrategy {
     
        private String emailId;
        private String password;
     
        public PaypalStrategy(String email, String pwd){
            this.emailId=email;
            this.password=pwd;
        }
     
        @Override
        public void pay(int amount) {
            System.out.println(amount + " paid using Paypal.");
        }
     
    }


public class Item {
 
    private String upcCode;
    private int price;
 
    public Item(String upc, int cost){
        this.upcCode=upc;
        this.price=cost;
    }
 
    public String getUpcCode() {
        return upcCode;
    }
 
    public int getPrice() {
        return price;
    }
 
}

    public class ShoppingCart {
     
   

 //List of items
    List<Item> items;
 
    public ShoppingCart(){
        this.items=new ArrayList<Item>();
    }
 
    public void addItem(Item item){
        this.items.add(item);
    }
 
    public void removeItem(Item item){
        this.items.remove(item);
    }
 
    public int calculateTotal(){
        int sum = 0;
        for(Item item : items){
            sum += item.getPrice();
        }
        return sum;
    }
 
    public void pay(PaymentStrategy paymentMethod){
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    }
}



public class ShoppingCartTest {
 
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
 
        Item item1 = new Item("1234",10);
        Item item2 = new Item("5678",40);
 
        cart.addItem(item1);
        cart.addItem(item2);
 
        //pay by paypal
        cart.pay(new PaypalStrategy("myemail@example.com", "mypwd"));
 
        //pay by credit card
        cart.pay(new CreditCardStrategy("Pankaj Kumar", "1234567890123456", "786", "12/15"));
    }
 
}

I want to ask what is use of strategy pattern here?Once we have created a strategy in main.We have access to Strategy class now.We can directly call pay() method from there?Why do we need interface , all which does is call a method?