vendredi 30 septembre 2022

Should I create an object and call function, or create static class function that takes in object?

I currently have this class:

class typeX_handler {
    SomeObject& toBeAltered;
    void function();
}

So in my main I am doing something like this:

SomeObject result = SomeObject() 

// Initialize all my handlers
TypeX_handler x = TypeX_handler(result);
...

// Some condition where I use this handler 
if (... == "type_x") {
    x.function();
}

else if ... Repeat for many other handlers

So by doing this, I'm essentially updating my SomeObject which I can return at the end. My question is that is it better to create a static function for the typeX_handler class as such:

class typeX_handler {
    static void function(SomeObject& toBeAltered);
}

// In the if-statement I call this instead
typeX_handler::function(result);

So that I do not need to initialize all of my handlers at the start? Or is it clearer that I initialize my handlers, because there may be cases where not all the handlers are utilized.

I did consider doing this in the if method:

if (... == "type_x") {
    // if (x is not initialized) { initalize x; }
    x.function();
}

But I'm also not sure how to implement this. As far as I am aware of, I have to utilize pointers to make x initially a NULL_PTR. Please advise on which design pattern to use!!

jeudi 29 septembre 2022

Why my code does not produce the pattern in the 2nd loop? (Python)

Language: Python Why my codes not work in the 2nd iteration? I'd like to understand what I'm doing wrong? I want to give input in row = 3 or 5 or x, and then I expect it to produce the following output pattern:

#When row = 3

1|. . #
2|. ##
3|###

Please note that the number of "." will be opposite to the number of "#" *i loop prints a new line, j loop prints "#", and k loop prints "."

''' row = 3

for i in range(1, row + 1):
    for j in range(1, i + 1):
        for k in range(1, (row - i) + 1):
            print(".", end= "")
        print("#", end="")
    print("")

'''

mercredi 28 septembre 2022

How to mark the modified fields in a class to be dirty

I have a class try to follow the active record pattern

class MyActiveRecord {
    int id;
    string name;
    int progress;
    ...
}

When I try to use this class to update the corresponding row of the SQL Data base, I want to mark the modified field to be "dirty". So, only the modified field, let's say progress will update the progress column in the data base.

My question is how to mark the modified field(s) to be dirty?

One way is to create booleans:

class MyActiveRecord {
    int id;
    boolean id_dirty;
    string name;
    boolean name_dirty;
    int progress;
    boolean progress_dirty;
    ...
}

Another way is to create enums of the fields and having a HashSet to contain the modified field enums.

Which way is better? Or is there another better way to mark the modified field(s) to be dirty?

Design Pattern to use for customizable/extendable classes with constructors

Starting with the use case.
Let's consider the base for this questions is a big framework and implementations of business objects of some software.

This software hast to be customized quite regularly, so it would be preferred that most of the C# objects are extendable and logic can be overriden. Even "model data".

The goal would be to be able to write code, create objects with input parameters - that may create more objects etc - and you don't have to think about whether those objects have derived implementations in any way. The derived classes will be used automatically.
For ease of uses a typesafe way to create the objects would be preferred as well.

A quick example:

public class OrderModel
{
    public int Id { get; set; }
    public string Status { get; set; }
}
public class CustomOrderModel : OrderModel
{
    public string AdditionalData { get; set; }
}
public class StockFinder
{
    public Article Article { get; }

    public StockFinder(Article article)
    {
        Article = article;
    }

    public virtual double GetInternalStock() { /*...*/ }

    public virtual double GetFreeStock() { /*...*/ }
}
public class CustomStockFinder : StockFinder
{
    public bool UsePremiumAvailability { get; }

    public CustomStockFinder(Article article, bool usePremiumAvailability)
        : base(article)
    {
        UsePremiumAvailability = usePremiumAvailability;
    }

    protected CustomStockFinder(Article article) : this(article, false) { } // For compatibility (?)

    public override double GetFreeStock() { /*...*/ }
}

In both cases I wanna do stuff like this

var resp = Factory.Create<OrderModel>(); // Creates a CustomOrderModel internally

// Generic
var finderGeneric = Factory.Create<StockFinder>(someArticle);

// Typesafe?
var finderTypesafe1 = Factory.StockFinder.Create(someArticle); // GetFreeStock() uses the new implementation
var finderTypesafe2 = Factory.StockFinder.Create(someArticle, true); // Returns the custom class already

Automatically generating and compiling C# code on build is not a big issue and could be done.
Usage of Reflection to call constructors is okay, if need be.
It's less about how complicating some code generation logic, written code analyzers, internal factories, builders etc are, and more about how "easy" and understandable the framework solution will be on a daily basis, to write classes and create those objects.

I thought about tagging the relevant classes with Attributes and then generating a typesafe factory class automatically on build step. Not so sure about naming conflicts, or references that might be needed to compile, as the constructor parameters could be anything.
Also, custom classes could have different constructors, so they should be compatible at each place in default code where they might be constructed already, but still create the custom object. In the custom code then you should be able to use the full custom constructor.

I am currently considering several different cases and possibilities, and can't seem to find a good solution. Maybe I am missing some kind of design pattern, or am not able to look outside of my bubble.

What would be the best design pattern or coding be to implement use cases like this?

How to organize the validation, so as not to violate the DDD principles?

I have decided to use 'Execute / CanExecute pattern' for validation of my entities. Also, I want to move my validation values (length of string, messages, etc) to XML file, but I am not sure that XmlReader logic in the Domain layer is an appropriate solution for it. (New to DDD.)

Where would you place the logic for reading an xml file according to DDD? Perhaps you can suggest another way to store validation data?

For example my Item class:

public class Item : Entity, IAggregateRoot
{
    public string IdentityGuid { get; private set; }

    public string Name { get; private set; }

    public string Description { get; private set; }

    public decimal Price { get; private set; }

    public string PictureFileName { get; private set; }

    public string PictureUri { get; private set; }

    public string CatalogTypeId { get; private set; }

    public CatalogType CatalogType { get; private set; }

    public string BrandId { get; private set; }

    public Brand Brand { get; private set; }

    // Quantity in stock
    public int AvailableStock { get; private set; }

    // Available stock at which we should reorder
    public int RestockThreshold { get; private set; }


    // Maximum number of units that can be in-stock at any time (due to physicial/logistical constraints in warehouses)
    public int MaxStockThreshold { get; private set; }

    /// <summary>
    /// True if item is on reorder
    /// </summary>
    public bool OnReorder { get; private set; }

    public Item(
        string name,
        string description,
        decimal price,
        string pictureFileName,
        string pictureUri,
        string catalogTypeId,
        CatalogType catalogType,
        string brandId,
        Brand brand,
        int availableStock,
        int restockThreshold,
        int maxStockThreshold,
        bool onReorder)
    {
        if (CanCreateItem(name, description, price, pictureFileName,
            pictureUri, catalogTypeId, catalogType, brandId, brand,
            availableStock, restockThreshold, maxStockThreshold).Any())
        {
            throw new CatalogDomainException($"Unable to create object {typeof(Item)} data is invalid.");
        }

        Name = name;
        Description = description;
        Price = price;
        PictureFileName = pictureFileName;
        PictureUri = pictureUri;
        CatalogTypeId = catalogTypeId;
        CatalogType = catalogType;
        BrandId = brandId;
        Brand = brand;
        AvailableStock = availableStock;
        MaxStockThreshold = maxStockThreshold;
        OnReorder = onReorder;
    }

    /// <summary>
    /// Validation for Creation of Item. Execute / CanExecute pattern
    /// <param name="name"></param>
    /// <param name="description"></param>
    /// <param name="price"></param>
    /// <param name="pictureFileName"></param>
    /// <param name="pictureUri"></param>
    /// <param name="catalogTypeId"></param>
    /// <param name="catalogType"></param>
    /// <param name="brandId"></param>
    /// <param name="brand"></param>
    /// <param name="availableStock"></param>
    /// <param name="restockThreshold"></param>
    /// <param name="maxStockThreshold"></param>
    /// <returns>int: Collection of string error message</returns>
    /// </summary>
    public IReadOnlyList<string> CanCreateItem(string name,
        string description,
        decimal price,
        string pictureFileName,
        string pictureUri,
        string catalogTypeId,
        CatalogType catalogType,
        string brandId,
        Brand brand,
        int availableStock,
        int restockThreshold,
        int maxStockThreshold
        )
    {
        var errors = new List<string>();

        // name
        if (string.IsNullOrEmpty(name))
            errors.Add("Name must be at least three characters long.");
        if (name.Length < 3)
            errors.Add("Name must be at least three characters long.");
        if (name.Length > 50)
            errors.Add("A name cannot be more than fifty characters long.");

        // description
        if (string.IsNullOrEmpty(description))
            errors.Add("Description must be at least fifth characters long.");
        if (name.Length < 5)
            errors.Add("Name must be at fifth three characters long.");
        if (name.Length > 1000)
            errors.Add("A name cannot be more than thousand characters long.");

        // price
        if (price < 0)
            errors.Add("Price must be greater than zero.");

        // pictureFileName
        if (string.IsNullOrEmpty(pictureFileName))
            errors.Add("PictureFileName cannot be empty.");

        // pictureUri
        if (string.IsNullOrEmpty(pictureUri))
            errors.Add("PictureUri cannot be empty.");

        // catalogTypeId
        if (string.IsNullOrEmpty(pictureUri))
            errors.Add("CatalogTypeId cannot be empty.");

        // catalogType
        if (string.IsNullOrEmpty(catalogTypeId))
            errors.Add("CatalogTypeId cannot be у.");

        // catalogType
        if (catalogType == null)
            errors.Add("CatalogType cannot be null.");

        // brandId
        if (string.IsNullOrEmpty(brandId))
            errors.Add("BrandId cannot be empty.");

        // brand
        if (brand == null)
            errors.Add("Brand cannot be null.");

        // availableStock
        if (availableStock < 0)
            errors.Add("AvailableStock must be Zero or greater.");

        // restockThreshold
        if (restockThreshold < 0)
            errors.Add("RestockThreshold must be Zero or greater.");

        // maxStockThreshold
        if (maxStockThreshold < 0)
            errors.Add("MaxStockThreshold must be Zero or greater.");

        return errors;
    }
}

My XML file with validation data. (Just for example)

<ItemValidationData>
  <ItemProperty>
    <Name>Name</Name>
    <ConstraintName>MinNameLength</ConstraintName>
    <Value>3</Value>
    <Message>Name must be at least three characters long.</Message>
  </ItemProperty>
  <ItemProperty>
    <Name>Name</Name>
    <ConstraintName>MaxNameLength</ConstraintName>
    <Value>50</Value>
    <Message>A name cannot be more than fifty characters long.</Message>
  </ItemProperty>
</ItemValidationData>

Add the Admin pattern to an existing software

My question is about design, Let's say that I built a parking system. This system has classes for entries, cars, slots, tickets ... and everything you can imaging in a parking lot, Obviously this system need's someone to control it, or maybe multiple people will work on it. I need a class diagram for User, Admin ext, I prefer if i have the ability to easily create new types of users that has different privileges. I tried the strategy pattern where every privilege has an allowed and not allowed strategy, and when I want to create a new type of user, I give it the appropriate strategies. I'm not sure if this is a good solution, can someone make a class diagram for the user, maybe using the strategy pattern, but feel free to use the solution that you think is more suitable for this problem. For the rest of the app use an abstraction, I don't think that it's important. I just need the user part.

also I want it to be like linux, You log in with your password as an admin or something else.

How to implement Protocol Buffer generated code with Object Oriented Design?

I have a question about the general case of implementing functionality regarding generated code/classes from Protocol buffers. General in the sense that, the problem that I am having is in Java right now, but the question is applicable to object-oriented programming as a whole...

Basically, the way that serialization and deserialization would work for my project normally is that I would write custom serializers and deserializers for json for each language that I'm working in, and these would covert json messages into classes that have fields from the json, but with custom methods that I write.

Using protocol buffers gives me a number of advantages, but one important one in my mind is that the automatically generated code means I am not having to write serializers and deserializers manually. However, it is unclear what the proper way is to implement logic that involves this deserialized data. The official tutorial (https://developers.google.com/protocol-buffers/docs/javatutorial#parsing-and-serialization) warns against using inheritance for a situation like this:

Protocol buffer classes are basically data holders (like structs in C) that don't provide additional functionality; they don't make good first class citizens in an object model. If you want to add richer behavior to a generated class, the best way to do this is to wrap the generated protocol buffer class in an application-specific class. Wrapping protocol buffers is also a good idea if you don't have control over the design of the .proto file (if, say, you're reusing one from another project). In that case, you can use the wrapper class to craft an interface better suited to the unique environment of your application: hiding some data and methods, exposing convenience functions, etc. You should never add behavior to the generated classes by inheriting from them. This will break internal mechanisms and is not good object-oriented practice anyway.

But I'm not sure what is supposed to be done instead...

My options appear to be:

  • Ignoring this warning and creating a class for inheritance anyways. This means modifying the automatically created protobuf code which I don't want to do, or as in this post (https://blog.teamdev.com/protobuf-serialization-and-beyond-part-3-value-objects-e3dc7b935ac), using a protoc plugin to automatically add this inheritance structure to the automatically generated types. A closed Github issue on protobuf (https://github.com/protocolbuffers/protobuf/issues/4481) talks about problems with this solution as well - although technically supported, the use of plugins is not well documented or supported and still goes against the warning from the tutorial. There may be some kind of casting wizardry I can do to have this work without modifying the generated protobuf code, but I'm not sure... This method seems to make the system easiest to change, as it is automatically responsive to changes in the underlying schema - only methods that serve a proper function (not getters and setters) would be written by me, and would throw compile-time exceptions if their underlying fields no longer work, making sure I make changes to only application code when my schema changes (exactly what I want).
  • Creating a wrapper class as suggested in the above warning, encapsulating the generated code. This follows the delegation design pattern, which to my understanding is not easily implemented in every language. In Java, for example, the delegation must be written manually and must be changed in code every time the protobuf schema changes, which is obviously not ideal, and I'm not sure how I would implement the Decorator/ Adapter patterns that I'm looking for without inheritance (see first point) or code duplication because of this. This also gets pretty wild as the size of the schema increases, and without an easy way to implement delegation I think this is unsustainable... (This stackoverflow answer and the comment below basically explains what my concern with this method is: https://stackoverflow.com/a/16360532/17885960). There is the Lombok delegation class (experimental), and Scala for example supports delegation natively, but I'm not sure this is the best way forward...
  • Not using Protobuf generated classes in domain logic, instead manually creating classes with custom logic and mapping the protobuf messages / generated classes to these custom objects as data enters/leaves the application. This is basically the same as what happens currently with JSON in the application, except instead of mapping JSON directly, I would be first converting the messages to protobuf generated classes, then coverting these protobuf generated classes into the custom classes. I might be able to get away with using something like gson in Java to handle the automated conversion between these two types (protobuf-generated class -> json -> custom class and vice versa), but this adds overhead to the system which never existed before (instead of just parsing json into a class, I'm parsing json into a class, then that class into another class), and I still won't be benefitting from the automatic methods created by the protobuf generated code. This method is the most serialization-format-agnostic, as the same classes that support json can support protobufs, but this method also seems to need the most boilerplate code out of all the options - I would be duplicating all the getters and setters of the protobuf generated classes, as well as writing domain logic, as well as writing converter classes/methods. This method is suggested in the following threads: https://softwareengineering.stackexchange.com/a/170822, https://stackoverflow.com/a/16360532/17885960, https://groups.google.com/g/protobuf/c/pABidPhYqIo).

The threads I find on this topic are old and sparse - is this a rare problem to have, is it too niche, or am I just overthinking things?

What is the best way forward, and how can I better understand how to think about and solve this kind of problem in the future?

mardi 27 septembre 2022

how to find open source monolith codebases?

I need to find monolith architecture codebases to make a research. Preferably in Python or JavaScript. Do you have a suggestion on how to find these codebases?

I currently searched for this topic on Github: https://github.com/topics/monolith

But it doesn't have many options.

What pattern should be used, strategy?

I do have a service which needs to handle two types of meal.

@Service
class MealService {

   private final List<MealStrategy> strategies;

   MealService(…) {
       this.strategies = strategies;
   }

   void handle() {
       var foo = …;
       var bar = …;
       strategies.forEach(s -> s.remove(foo, bar));
   }
}

There are two strategies, ‘BurgerStrategy’ and ‘PastaStrategy’. Both implements Strategy interface with one method called remove which takes two parameters.

BurgerStrategy class retrieves meals of enum type burger from the database and iterate over them and perform some operations. Similar stuff does the PastaStrategy.

The question is, does it make sense to call it Strategy and implement it this way or not?

Also, how to handle duplications of the code in those two services, let’s say both share the same private methods. Does it make sense to create a Helper class or something?

How to implement a list with decorated elements

Having a result of REST or JPA query I have an often requirement to decorate items with some additional attributes that come from some other queries. To avoid coping and processing the list ( the result ) I am thinking about a runtime universal list decorator that contains items decorated at runtime.

The question: is there any standard pattern for that?

Example: as a result of REST query I have list of people. I need to decorate each person with vacation quota.

I searched occasionally for such pattern for many years but couldn't find anything.

What's an appropriate design pattern to call outer struct's method in Golang?

For example, I have a parent struct Connection and a child struct Dialect as follows:

type Connection struct {
    conn *net.TCPConn
    databaseDialect DatabaseDialect
}

func (c *Connection) modifySQL(sql string) (string, error) {
}

// Close cleans up
func (c *Connection) Close() error {
    ...
}

func (c *Connection) handleConnection() error {
    c.databaseDialect = &PostgreSQLDialect{
        conn: c.conn,
        modifySQLFunc: c.modifySQL,
    }
    return dialect.HandleConnection()
}

type DatabaseDialect interface {
    HandleConnection()
}

type PostgreSQLDialect struct {
    conn *net.TCPConn
    modifySQLFunc func(string) (string, error)
}

func (d *PostgreSQLDialect) HandleConnection() error {
    buff := make([]byte, 0xffff)
    d.conn.Read(buff)
    sql := parseToSQL(buff) // parse buffer to SQL statements
    
    // call outer's function here
    sql, err = d.modifySQLFunc(sql)
    ...
}

You can see that the outer function modifySQL is passed in PostgreSQLDialect. but things can be more complicated. Say if we got more outer functions needed to be called. For instance, when a connection is closed. We need to call the outer function Close() to clean up resources. So I'm curious if PostgreSQLDialect needs to have a reference variable to the outer struct Connection. But I just feel like it's not a good design to make my code well-architectured.

Is there any design pattern good for this case? Any open source repo, source code or article is welcome.

React - Best practice to organize mass API-calls/models and its data/functions

Im not happy how i handle API calls and its data.

My application is downloading all needed data right after logging in and frequently asking the API for updates. If there are any updates the will be added to the data. Because all data depending on each other they all need to know each other.

I try different ways to separate each model to one js.-file but ended up creating one big file (2000 lines of code) which contains all models and its functions (login, logout, resetPasswd, insert, update, remove, getForeignObjectByID, ...). I initialize this file at the beginning(App.js) as custom hook and provide it to every child.

I think my case isn't that special, i wonder why i cant find any informations about how to manage mass models. So what is the best practise to handly stuff like this?

Here is the code. I had to cut some parts out, so some thinks doesnt make sence, dont wonder. Please focus on my question, i try to clean this up step by step.

import { useState, useEffect } from 'react';
import FormatDate from "../format.date"

export default function useData() {
const url = "https://123.123.123.123:1234/"

const [informations, setInformations] = useState([])
const [owners, setOwners] = useState([])
const [users, setUsers] = useState([])
const [services, setServices] = useState([])
const [settings, setSettings] = useState([])
const [loadingState, setLoadingState] = useState("waiting...")
const [loadingProgression, setLoadingProgression] = useState(0)

const { formatDate } = FormatDate()



useEffect(() => {
    if (!token) return
    loadData(token)
}, [token])



const login = async (credentials) => {
    const res = fetch(url + 'login',
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(credentials)
        })
        .then(data => data.json())
        .catch((error) => {
            return { success: false, error: true, errorText: "Login fehlgeschlagen" }
        })

    return await res;
}

const confirmMail = async (mail, key) => {
    const res = fetch(url + `mailConfirm?mail=${encodeURIComponent(mail)}&key=${encodeURIComponent(key)}`,
        {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            }
        })
        .then(data => data.json())
        .catch((error) => {
            return { success: false, error: true, errorText: "Mail-Bestätigung fehlgeschlagen" }
        })

    return await res
}

const resetPasswortRequest = async (mail) => {
    const res = fetch(url + `resetPasswordRequest`,
        {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                "mail": mail
            })
        })
        .then(data => data.json())
        .catch((error) => {
            return { success: false, error: true, errorText: "Passwort zurücksetzen fehlgeschlagen" }
        })

    return await res
}

const resetPasswort = async (mail, password, key) => {
    const res = fetch(url + `resetPassword`,
        {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                "mail": mail,
                "password": password,
                "key": key
            })
        })
        .then(data => data.json())
        .catch((error) => {
            return { success: false, error: true, errorText: "Passwort zurücksetzen fehlgeschlagen" }
        })

    return await res
}

const registrate = async (mail, password) => {
    const res = fetch(url + 'signup',
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                "email": mail,
                "password": password,
                "key": "?"
            })
        })
        .then(data => data.json())

    return await res;
}

const loadData = async (token) => {
    setLoadingReady(false)

    setLoadingState("Lade Informationen")
    setLoadingProgression(30)
    const i = await loadInformations(token)

    setLoadingState("Lade Eigentümer")
    setLoadingProgression(50)
    const o = await loadOwners(token)

    setLoadingState("Lade Services")
    setLoadingProgression(60)
    const s = await loadServices(token)

    // setLoadingState("Lade Einstellungen")
    // setLoadingProgression(65)
    // const s2 = await loadSettings(token)

    setLoadingState("Lade Benutzer")
    setLoadingProgression(70)
    const u = await loadUsers(token)

    setLoadingProgression(80)
    setLoadingState("Verarbeite Daten")

    if (!o.error) {
        var dataOwners = convertID(o)
        setOwners(relateOwners(dataOwners))
    }

    if (!i.error) {
        var dataInformations = convertID(i)
        setInformations(relateInformations(dataInformations, ...))
    }

    if (!s.error) {
        var dataServices = convertID(s)
        setServices(dataServices)
    }

    // if (!s2.error) {
    //     setSettings(s2)
    // }

    if (!u.error) {
        var dataUsers = convertID(u)
        setUsers(dataUsers)
    }

    setLoadingProgression(100)
    setLoadingState("Fertig!")
    setLoadingReady(true)
}

//#region ########## Informations ##########

const loadInformations = async (t2) => {
    const res = await fetch(url + `informations`,
        {
            method: "GET",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + t2
            }
        })
    return await res.json()
}

const deleteInformation = async (information) => {
    return await fetch(url + `informations/${information.id}`,
        {
            method: "DELETE",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            }
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            const filtered = informations.filter((el) => {
                return el.id !== information.id;
            })
            setInformations(filtered)
            return { success: true, response: information }
        } else {
            const errorText = "Information konnte nicht gelöscht werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Information konnte nicht gelöscht werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const updateInformation = async (information) => {
    ...

    return await fetch(url + `informations/${u?????.id}`,
        {
            method: "PUT",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(u?????)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            const relatedInformations = relateInformations(
                informations.map((b) => b.id === information.id ? information : b), ...)

            setInformations(relatedInformations)
            return { success: true, response: information }
        } else {
            const errorText = "Information konnte nicht gespeichert werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Information konnte nicht gespeichert werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const insertInformation = async (information) => {
    var uInformation = JSON.parse(JSON.stringify(information))
    delete uInformation["?????Obj"]
    delete uInformation["_id"]
    delete uInformation["?????Index"]
    delete uInformation["x"]
    delete uInformation["y"]
    delete uInformation["height"]
    delete uInformation["width"]
    delete uInformation["domain"]

    return await fetch(url + `informations`,
        {
            method: "POST",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(uInformation)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            var newInformation = relateInformation({ ...uInformation, id: res.id }, ?????s)
            setInformations([...informations, newInformation])
            return { success: true, response: newInformation }
        } else {
            const errorText = "Information konnte nicht hinzugefügt werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Information konnte nicht hinzugefügt werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const relateInformations = (dataInformations, data?????s) => {
    var newInformations = []
    dataInformations.forEach(i => {
        var newInformation = relateInformation(i, data?????s)
        newInformations.push(newInformation)
    });

    return newInformations
}

const relateInformation = (information, data?????s) => {
    var newInformation = JSON.parse(JSON.stringify(information))

    if (newInformation.date.$date) {
        newInformation.date = formatDate(newInformation.date.$date, "yyyy-MM-dd")
    }

    if (newInformation.status) {
        switch (newInformation.status) {
            case 0:
                newInformation.statusText = "Offen"
                break;
            case 1:
                newInformation.statusText = "Erledigt"
                break;
        }
    }

    var ????? = null
    for (var i = 0; i < data?????s.length && ????? == null; i++)
        if (data?????s[i].id == newInformation.?????)
            ????? = data?????s[i]
    newInformation.?????Obj = ?????

    return newInformation
}

const emptyInformation = () => {
    return {
        text: "",
        ?????: "",
        date: formatDate(new Date(), "yyyy-MM-dd"),
        status: 0
    }
}

//#endregion

//#region ########## Owners ##########

const loadOwners = async (t2) => {
    const res = await fetch(url + "owners",
        {
            method: "GET",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + t2
            }
        })
    return await res.json()
}

const deleteOwner = async (owner) => {
    return await fetch(url + `owners/${owner.id}`,
        {
            method: "DELETE",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            }
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            const filtered = owners.filter((el) => {
                return el.id !== owner.id;
            })
            setOwners(filtered)
            return { success: true, response: owner }
        } else {
            const errorText = "Eigentümer konnte nicht gelöscht werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Eigentümer konnte nicht gelöscht werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const updateOwner = async (owner) => {
    delete owner["_id"]
    delete owner["fullName"]

    return await fetch(url + `owners/${owner.id}`,
        {
            method: "PUT",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(owner)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            setOwners(owners.map((o) => o.id === owner.id ? relateOwner(owner) : o))
            return { success: true, response: owner }
        } else {
            const errorText = "Eigentümer konnte nicht gespeichert werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Eigentümer konnte nicht gespeichert werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const insertOwner = async (owner) => {
    return await fetch(url + `owners`,
        {
            method: "POST",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(owner)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            var newOwner = { ...owner, id: res.id }
            setOwners([...owners, newOwner])
            return { success: true, response: newOwner }
        } else {
            const errorText = "Eigentümer konnte nicht hinzugefügt werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Eigentümer konnte nicht hinzugefügt werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const getOwnerByID = (id) => {
    for (let i = 0; i < owners.length; i++) {
        if (owners[i].id == id) {
            return owners[i]
        }
    }
}

const relateOwners = (dataOwners) => {
    var newOwners = []
    dataOwners.forEach(o => {
        newOwners.push(relateOwner(o))
    });

    return newOwners
}

const relateOwner = (owner) => {
    var newOwner = JSON.parse(JSON.stringify(owner))
    newOwner.fullName = newOwner.firstname + " " + newOwner.lastname
    return newOwner
}

const emptyOwner = () => {
    return {
        firstname: "",
        lastname: "",
        street: "",
        zip: "",
        place: "",
        country: "",
        telefon: "",
        mail: "",
        commission: 1,
        customSalutation: false,
        salutation: ""
    }
}

//#endregion

//#region ########## Users ##########

const loadUsers = async (t2) => {
    const res = await fetch(url + "users",
        {
            method: "GET",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + t2
            }
        })
    return await res.json()
}

const insertUser = async (user) => {
    return await fetch(url + `users`,
        {
            method: "POST",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(user)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            var newUser = relateUser({ ...user, id: res.id })
            setUsers([...users, newUser])
            return { success: true, response: newUser }
        } else {
            const errorText = "Benutzer konnte nicht hinzugefügt werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Benutzer konnte nicht hinzugefügt werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const updateUser = async (user) => {
    delete user["_id"]

    return await fetch(url + `users/${user.id}`,
        {
            method: "PUT",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(user)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            setUsers(users.map((u) => u.id === user.id ? relateUser(user) : u))
            return { success: true, error: undefined, response: user }
        } else {
            const errorText = "Benutzer konnte nicht gespeichert werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Benutzer konnte nicht gespeichert werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const deleteUser = async (user) => {
    return await fetch(url + `users/${user.id}`,
        {
            method: "DELETE",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            }
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            const filtered = users.filter((el) => {
                return el.id !== user.id;
            })
            setUsers(filtered)
            return { success: true, error: undefined, response: user }
        } else {
            const errorText = "Benutzer konnte nicht gelöscht werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Benutzer konnte nicht gelöscht werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const relateUsers = (dataUsers) => {
    var newUsers = []
    dataUsers.forEach(u => {
        newUsers.push(relateUser(u))
    });

    return newUsers
}

const relateUser = (dataUser) => {
    var newUser = JSON.parse(JSON.stringify(dataUser))
    return newUser
}

const emptyUser = () => {
    return {
        email: "",
        password: "",
        permissions: {
            ownerView: true,
            ownerEdit: true,
            ?????View: true,
            ?????Edit: true,
            tenantView: true,
            tenantEdit: true,
            informationView: true,
            informationEdit: true,
            serviceTemplateView: true,
            serviceTemplateEdit: true,
            userView: false,
            userEdit: false

        }
    }
}

//#endregion

//#region ########## Services ##########

const loadServices = async (t2) => {
    const res = await fetch(url + "serviceTemplates",
        {
            method: "GET",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + t2
            }
        })
    return await res.json()
}

const insertService = async (service) => {
    return await fetch(url + `serviceTemplates`,
        {
            method: "POST",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(service)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            const newService = { ...service, id: res.id }
            setServices([...services, newService])
            return { success: true, error: undefined, response: newService }
        } else {
            const errorText = "Service konnte nicht hinzugefügt werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Service konnte nicht hinzugefügt werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const updateService = async (service) => {
    delete service["_id"]
    return await fetch(url + `serviceTemplates/${service.id}`,
        {
            method: "PUT",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            },
            body: JSON.stringify(service)
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            setServices(services.map((s) => s.id === service.id ? service : s))
            return { success: true, error: undefined, response: service }
        } else {
            const errorText = "Service konnte nicht gespeichert werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Service konnte nicht gespeichert werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const deleteService = async (service) => {
    return await fetch(url + `serviceTemplates/${service.id}`,
        {
            method: "DELETE",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + token
            }
        }
    ).then((res) => {
        return res.json();
    }).then((res) => {
        if (!res.error) {
            const filtered = services.filter((el) => {
                return el.id !== service.id;
            })
            setServices(filtered)
            return { success: true, error: undefined, response: service }
        } else {
            const errorText = "Service konnte nicht gelöscht werden!\n" +
                errorTexts[parseInt(res.error)]
            return { success: false, error: res.error, errorText: errorText }
        }
    }).catch((error) => {
        const errorText = "Service konnte nicht gelöscht werden!\n" + error
        return { success: false, error: true, errorText: errorText }
    })
}

const emptyService = () => {
    return {
        name: "",
        parentType: "None",
        commission: 100,
        ?????PerPiece: 0,
        ?????Initial: 0
    }
}

//#endregion


const getCurrentDate = (days = 0) => {
    return new Date(new Date().setDate(new Date().getDate() + days))
}

return {
    data: {
        informations,
        setInformations,
        loadInformations,
        insertInformation,
        updateInformation,
        deleteInformation,
        emptyInformation,
        owners,
        setOwners,
        insertOwner,
        updateOwner,
        deleteOwner,
        getOwnerByID,
        emptyOwner,
        services,
        setServices,
        insertService,
        updateService,
        deleteService,
        emptyService,
        users,
        setUsers,
        insertUser,
        updateUser,
        deleteUser,
        emptyUser,
        loadData,
        login,
        registrate,
        confirmMail,
        resetPasswortRequest,
        resetPasswort,
        loadingState,
    }
}

}

Thaks for your time

lundi 26 septembre 2022

Improving large switch case

I have an API (built with spring boot) which has a method that provides a template file on format .xlxs delivered on a response DTO object with a base64 inside of it.

    @GetMapping("/getLoadTemplate")
    public ResponseEntity<?> getLoadTemplate(@RequestParam(name = "type", defaultValue = "!") String type) {
        ResponseDTO responseDTO;
        if (notInTypes(type))
            return ResponseEntity.badRequest().body(badRequest("Tipo de archivo invalido."));
        try {
            responseDTO = loadQuotasService.getFileTemplate(type);
            return ResponseEntity.status(responseDTO.getStatus()).body(responseDTO);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(errorResponse(logger, e));
        }
    }

The request object is a simple string that can be on any of the types of the classes that have a xlxs template, so each class has it own LOAD_NAME value. Example public final static String LOAD_NAME = "POLITICAS_AFILIADO"

public static boolean notInTypes(String type){
        if(type == null) return true;
        String[] validTypes = {QuotaLoad.LOAD_NAME, QuotaModify.LOAD_NAME, QuotaState.LOAD_NAME,
                AffiliatePolitics.LOAD_NAME, AffiliateRisk.LOAD_NAME, BuyerEvaluation.LOAD_NAME,
                HabeasRegister.LOAD_NAME, QuotaBuyer.LOAD_NAME, ClintonList.LOAD_NAME, BuyerQualification.LOAD_NAME};
        return !Arrays.asList(validTypes).contains(type);
    }

PROBLEM This is the service method ... It's filled of repetitive code and a super big switch block. Will be difficult to mantainf

public ResponseDTO getFileTemplate(String type) {
        ASRFile template = null;
        switch (type) {
            case QuotaLoad.LOAD_NAME:
                template = fileRepository.findByFileOriginalNameAndCategory(QuotaLoad.TEMPLATE, QuotaLoad.CATEGORY);
                break;
            case QuotaModify.LOAD_NAME:
                template = fileRepository.findByFileOriginalNameAndCategory(QuotaModify.TEMPLATE, QuotaModify.CATEGORY);
                break;
            case QuotaState.LOAD_NAME:
                template = fileRepository.findByFileOriginalNameAndCategory(QuotaState.TEMPLATE, QuotaState.CATEGORY);
                break;
            case AffiliatePolitics.LOAD_NAME:
                template = fileRepository.findByFileOriginalNameAndCategory(AffiliatePolitics.TEMPLATE,
                        AffiliatePolitics.CATEGORY);
                break;
            case AffiliateRisk.LOAD_NAME:
                template = fileRepository.findByFileOriginalNameAndCategory(AffiliateRisk.TEMPLATE,
                        AffiliateRisk.CATEGORY);
                break;
            case BuyerEvaluation.LOAD_NAME:
                template = fileRepository.findByFileOriginalNameAndCategory(BuyerEvaluation.TEMPLATE,
                        BuyerEvaluation.CATEGORY);
                break;
// more equal code ...

How can I impprove this repetitive code?

Android list row: image+text+image

I'm creating a list of items with a personalized layout for the rows. In each row I want to have two images of fixed size:

  • one must contact its left border with the left border of the row layout (red square).
  • the other one must contact its right border with the right border of the row layout (orange square)

In between these images I want to have some extra elements inside a layout (green area). Thus, the size of this layout should be match_parent, but without hiding neither of the previous two images.

enter image description here

How can I do this?

I'm trying to put three linear layouts, wrapping to width the first and the third, and matching_parent the green one, but the green is hidding the orange.

Factory pattern with friend class in c++ [duplicate]

I am trying to implement factory pattern with private constructor and friend class. But below piece of code is getting failed. What could be the reason of failing?

class DFactory;

class Database {
public:
    virtual void CreateConnection() = 0;
    virtual ~Database() {};
};

class SQL : public Database {
private:
    SQL();
    friend class DFactory;
public:
    void CreateConnection(){}
};

// Factory class
class DFactory {
public:
    static Database* createDb() {
        return new SQL();
    }
};

// Driver program
int main() {
    Database *db = DFactory::createDb();
    db->CreateConnection();
    return 0;
}

This is the compiler error that I am getting

Could anyone help me to suggest the problem?

Fallback function in python

is there some kind of fallback function (Solidity analogy) in python? A fallback function is always called when no corresponding method is found in a class.

For example I have class A with no methods, but only a fallback function:

class A:
   def fallback(self, *args, **kwargs):
       # Somehow get the function name from kwargs
       print(f"Function {kwargs['function_name']} doesn't exist}"

So, when I call a nonexistent function I should get "Function non_existent doesn't exist", instead of AttributeError Exception.

a = A()
a.non_existent()

dimanche 25 septembre 2022

Is there a design pattern for this usage?

(Not necessarily restricted to Rust, it happens to be the tech stack I'm working with)

My use case is the following: users would like to measure external variables (eg. amperage, temperature, anything numerical) and pipe that measurement into a public API I am building. Let's say that users will perform their measurement via some Device and feed that input into my Analyser. The user will repeatedly measure and feed the measurement into my Analyser; the analyser generates an AnalyserOutput which the user uses as feedback for their device. High-level pseudocode looks like this:

// User inits their device. This can be anything the user wishes to use
let device = TemperatureGauge::Device::new();

// Init analyser (my public API)
let analyser = Analyser::new();

loop {
   // read some value
   let read_val: f64 = device.read();
   
   // problem: 
   // calculate feedback immediately after read
   // if there was a significant delay between these
   // calls eg. I inserted a thread::sleep(1000)
   // then the output generated would be inaccurate. How can
   // I enforce that there is nothing between these two
   // invocations?
   let output_feedback = analyser.next(read_val);

   // set some external variable via device based on feedback
   device.set(read_val + output_feedback);

   thread::sleep(1);
}

Here is the problem: the analyser.read(read_val) method is dependent on the time at which the current read_val was read and the time in which the previous read_val was read at. This means that I need the user to call .next() immediately after their .read() invocations.

I'm struggling with designing an API to enforce this constraint. I have no control over what and how the user is measuring. It could be some driver or it could be a simple calculation. Now, I'm stuck with assuming that the user has invoked my API under the correct circumstances.

Are there design patterns that can help me enforce this constraint: immediately following some-kind of a user 'read' invocation is an analyser.read() invocation?

Visual builder to work with manually hard-coded templates/components

I wonder, is it possible to create a visual no-code builder to work with JS components (e.g. React JSX) if them are manually hard-coded before?

Let me explain what I mean.

Suppose a simple React component pages/index.js previously written by a developer manually:

function HomePage() {
    return <div>Welcome to Next.js!</div>
}

export default HomePage

How can we change such a component in the front-end using a visual builder?

For example, we want to add a new HTML element (e.g. H1) inside the existing div.

As I can understand, the builder first needs to know in which JS file the HTML markup is stored to update it. So we can add id="homepage" to the div first and then store a relation as a config like

{"homepage": "pages/index.js"}

And now if we add a new element inside <div id="homepage">, the builder adds the element to the DOM of the div at the client, then takes the whole updated DOM of the div and writes back to the file index.js

Ok, but the file contains not only HTML markup - it's JS (React) code.

How to keep all the JS code e.g. function HomePage(), return, export default and so on ?

As an option, we can separately load all the JS code as HTML including non-HTML code as #text nodes. Then update the DOM and re-write everything back to the file.

But it sounds complicated and may cause unexpected issues.

So what solution would be the best?

Or maybe there is a ready React-specific solution?

Or maybe it's a bad idea at all to parse and re-write manually hard-coded components by visual builder and the only solution is to store everything as JSON like "homepage":{"div", {"class":""}, "Welcome..."} which is more easy for re-writing ? (but requires a new render)

samedi 24 septembre 2022

Which design pattern reduces repetition in this validation inputs code

Want to reduce code from these validations, these validators' classes verify and return if inputs are valid or invalid, it's a reduction, I will validate some panels and almost 40 fields. Want to see if there is some pattern to simplify this, code is more than 300 lines which I believe to be a bad practice.

package Validation1;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MinimalReproducibleExampleValidation {

public static void main(String[] args) {

    boolean saveToDatabase = true;

    String name = "Richard";
    String idCard = "123456789";
    String address = "Main Street 454";

    Entity entity = new Entity ();

    /// Name Validation
    if (saveToDatabase) {
        ValidationEntity nameValidation = new ValidationEntity(ValidationEntity.Regex.Alphabetic, name, "ID Card", 0, 13);
        saveToDatabase = nameValidation.isValid();
        entity.setName(name);
    }
    
    /// ID Card Validation
    if (saveToDatabase) {
        ValidationEntity idCardValidator = new ValidationEntity(ValidationEntity.Regex.Numerical, idCard, "ID Card", 0, 13);
        saveToDatabase = idCardValidator.isValid();
        entity.setIdCard(idCard);
    }
    
    /// EMail Validation
    if (saveToDatabase) {
        ValidationEntity emailValidator = new ValidationEntity(ValidationEntity.Regex.AlphaNumerical, address,           "Address", 1, 9);
        saveToDatabase = emailValidator.isValid();
        entity.setAddress(address);
    }
    // If every field is valid, save
    if (saveToDatabase) {
        new EntityDao().save(entity);
    }
}
}

class ValidationEntity {

    private Regex regex;
    private String input;
    private String errorMessage;
    private Integer minimum;
    private Integer maximum;

public ValidationEntity(Regex regex, String input, String errorMessage, int minimum, int maximum) {
    this.regex = regex;
    this.input = input;
    this.errorMessage = errorMessage;
    this.minimum = minimum;
    this.maximum = maximum;
}

public boolean isValid() {
    Pattern pattern = Pattern.compile(getRegexFormat(), Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(input);
    return matcher.matches();
}

public String getRegexFormat() {
    return "[" + regex.regexValue + "]{" + minimum + "," + maximum + "}";
}

public enum Regex {
    LowercaseAlphabetic("a-f"), UppercaseAlphabetic("A-F"), Numerical("0-9"), Alphabetic("a-fA-F"),
    AlphaNumerical("a-fA-F");

    public String regexValue;

    Regex(String regexValue) {
        this.regexValue = regexValue;
    }
}
}

class EntityDao {
public void save(Entity entity) {
    System.out.println("Saving the model!");
}
}

class Entity {

private String name;
private String idCard;
private String address;

public void setIdCard(String idCard) {
    this.idCard = idCard;
}

public void setName(String name) {
    this.name = name;
}

public void setAddress(String address) {
    this.address = address;
}

public String getIdCard() {
    return idCard;
}

public String getIdName() {
    return name;
}

public String getAddress() {
    return address;
}
}

Which design pattern reduces boilerplate when set method is what varies throughout the code

All this code happens when I press save button: Regex validation, JOptionPane Error Messages, and other behaviours like red spot around text field, I want to be cleaner:

/*
TextFieldValidator: Regex type, textFieldName, 
name of the field for error message, minimum size for 
validation, maximum size for validation.    
*/

public void actionPerformed(ActionEvent e) {
boolean lastModelIsValid=true;

///Id Card validation
TextFieldValidator idCardModel = new TextFieldValidator(
                    Regex.Numerical, idCardNumberTextField,
                    "ID Card Number", 9, 9);

         if (lastModelIsValid) {
            lastModelIsValid= idCardModel.isValidAndSendErrorMessage();
                            
            
                documents.setIDCardNumber(
                        Integer.getInteger(idCardModel.getTextFieldContent()));
            }


///EMail validation        
TextFieldValidator emailModel = new TextFieldValidator(
                    Regex.Alphanumerical, emailTextField,
                    "Email", 3, 20);

      if (lastModelIsValid) {
            lastModelIsValid= emailModel.isValidAndSendErrorMessage();                              
            
                documents.setEmailAddress(
                        emailModel.getTextFieldContent());
            }

 ///Twenty Fields more...

I thought about implementing something like that, but for me it is still too much code:

public void actionPerformed(ActionEvent e) {

boolean saveToDatabase=true;

///EMail validation   
if(new TextFieldValidator(Regex.Alphanumerical, emailTextField,
                    "Email", 3, 20).isValidAndSendErrorMessage()){
documents.setEmailAddress(Type.STRING, emailTextField.getText());
}
else
{
 saveToDatabase=false;
}  

///ID Card validation  
if(new TextFieldValidator(Regex.Numerical, idCardNumberTextField,
                    "ID Card", 9, 9).isValidAndSendErrorMessage()){
documents.setIdCardNumber(Type.INTEGER, idCardTextField.getText());
}
else
{
saveToDatabase=false;
}  
/// Twenty Fields more...

Not able to solve a specific C++ pattern problem

I tried to make this problem but not getting solution . I want to print the pattern using c++ - This is pattern -

I tried this code but it is printing in reverse order .

  using namespace std;

  int main() {
    int n;
    cin>>n;
    
    int i = 1;
    
    while(i<=n){
        int j =1;
        while(j<=n){
            cout<<j;
            j=j+1;
        }
        cout<<endl;
        i=i+1;
    }

    return 0;
}

Output - 123 123 123

Can you please tell how to print that ?

vendredi 23 septembre 2022

How to implement copy/past in mvp?

I tried to implement a simple File Manager based on MVP pattern that support renaming,deleting or copying selected files. I am struggling to implement copy/past feature in the right way. Here is the UI: enter image description here what's the best approach to do that under MVP pattern?

memento pattern - encapsulation and reusability of memento object

class Originator {
   private String state;
   Originator(String state) {
        this.state = state;
   }
   
   public void setState(String newState) {
        this.state = newState;
   }
   
   public Memento createMemento() {
        return new Memento(state);
   }
   
   public void restoreState(Memento memento) {
        // HOW to access private state of memento??
   }
}


class Memento {
   private String state;
   Memento(String state) {
        this.state = state;
   }
}


class CareTaker {
    public static void main(String[] args) {
        Originator originator = new Originator("state");
        Memento memento = originator.createMemento();
        
        originator.setState("new state");
        originator.restoreState(memento);
    }
}

I'm trying to implement memento pattern. I've made the state in Memento class private so that it is not accessible by caretaker. But on passing the memento object to originator, it will not be able to access the state of memento itself.

To resolve this, we can do few things, but there are disadvantages to it, thats why I didnt do them.

  1. Make state in memento public: The disadvantage is that it will not follow encapsulation of internal state.
  2. Make memento class internal to originator class: The disadvantage is that memento class will be bound to originator class and will not be reusable by other originators.
  3. Passing the originator reference in constructor of memento so that memento can itself restore the state of originator: The disadvantage is that memento class will be bound to single originator object and will not be reusable by other originators.

Please suggest solution where we follow encapsulation and we can also support reusability of memento object.

Go: Enforce fields of object passed into function?

I’m working on a project where I have two structs and I'd like to be able to perform the same logic on them without writing two different object methods, but I'm unsure how to enforce fields for an interface. For example, imagine I have the following two structs, with many differing fields but one that they share:

type Item1 struct {
    itemField            string
    ...some other fields
}

type Item2 struct {
    itemField            string
    ...some other fields that differ from those of Item1
}

And where these items have several differing functions, but one that they share:

func (Item1) ItemLogic() {
    --some logic--
}

func (Item2) ItemLogic() {
    --some different logic--
}

I want to group together a function that will do some upfront checks on these items before handling the item logic, but I don't want to have to write two separate functions to do so. I can write an interface so that I can pass both Item1 and Item2 in like so:

type IItem interface {
    ItemLogic()
}

but I can't enforce that the fields that get passed in as part of the function have a a field itemField, so that I could write a function like this:

func MainFunction(item IItem) {
    if item.ItemField == "..." {
          ....
    }

    item.ItemLogic()
}

The problem here is I could theoretically pass in an item that has an ItemLogic function but that lacks an ItemField field, resulting in a nil pointer. Is there some way I'm unaware of to enforce that field? Or, is there some better design I'm missing? I imagine I could make use of the reflect package in Go to check if the passed in object has the field, but it feels messy (I'd rather just not allow someone to pass a bad object in). Is there a better way?

Ansible: How to specify 'hosts:' value with patterns?

I have an inventory file that is dynamically generated with stanzas/groups in it. For example:

[ABC_foo_something]
server1
server2

[ABC_foo_somethingelse]
server3
server4

[ABC_bar_otherthing]
server5
server6

How can I specify a pattern for my playbook to run on e.g. all ABC_foo* groups.

---
- name: some playbook
  hosts: ABC_foo*
  tasks: etc..etc..

The problem is that the entire string is not known because they are dynamically created. I only know the first few chunks of the pattern and the rest should be wildcarded somehow.

jeudi 22 septembre 2022

Reverse right angle triangle pattern with numbers and asterisks using for-loops in C++

first time posting here, I'd like help with getting the output of the code upside down while still using the for commands, below is the best I can put in a clarification.

Desired Output:                 Actual Output:

123456                            1*****
12345*                            12****
1234**                            123***
123***                            1234**
12****                            12345*
1*****                            123456

Code:

#include <iostream>

using namespace std;

int main() {
    int num, row, integ;

    cout << "Please enter size: ";
    cin >> integ;

    for (row = 1; row <= integ; row++) {
        for (num = 1; num <= row; num++) {
            cout << num;
        }
        for (; num <= integ; num++) {
            cout << "*";
        }
        cout << endl;
    }
}

mercredi 21 septembre 2022

Design Pattern to combine runtime data with data loaded from a JSON

I have a data class:

public Data
{
    Foo MyFoo
    Bar MyBar
}

Foo is something that needs to a lot of changes and cleaning up to be useful. So I have an interface

public IFooTransformation
{
    Foo Transform(Foo foo)
}

Users create lists of IFooTransformation that are stored in JSON files and loaded at runtime.

foreach (var transformation in transformations)
{
    foo = transformation.Transform(foo);
}

This worked great until now I need to create an AddBarTransformation. All the other transformations include all the properties they need in the JSON, but MyBar is only available at runtime.

Is there a design pattern to help me get MyBar into the AddBarTransformation?

So far I've thinking:

  1. Using a custom JsonConverter that would Set AddBarTransformation's Bar to MyBar.
    • This might work but is a little janky and I haven't figured it out yet.
  2. Changing the interface to accept a Data rather than a Foo
    • This feels bad since the other Transformations only need Foo
  3. Using reflection to loop over the transformations and fill in if any need a Bar.
  4. Separate the logic and data of the IFooTransformation into and use a Builder or a Factory to get the matching logic class while knowing this one needs a Bar passed in.
    • Seems like a lot of complexity when something like 2 is really easy.

Design pattern for messaging service

Helllo,

I'm looking for a design pattern to implement in Java to meet requirements:

  • Having a list of Contacts (let's say Contact is an object with some fields)
  • Single contact record should have information thorugh which channel and which provider message should be send
  • Depends on situation there could be need to send messages to list of above contacts
  • There may be possibile different channels (email/sms/slack etc.) and different msg providers (integratio with 3rd party systems: Twilio/Slack/Messenger etc)

Could you please suggest what design pattern here would be most appropriate?

mardi 20 septembre 2022

Best Practice for OOP function with multiple possible control flows

In my project, I have this special function that does needs to evaluate the following:

  1. State -- represented by an enum -- and there are about 6 different states
  2. Left Argument
  3. Right Argument

Left and Right arguments are represented by strings, but their values can be the following:

  1. "_" (a wildcard)
  2. "1" (an integer string)
  3. "abc" (a normal string)

So as you can see, to cover all every single possibility, there's about 2 * 3 * 6 = 36 different logics to evaluate and of course, using if-else in one giant function will not be feasible at all. I have encapsulated the above 3 input into an object that I'll pass to my function.

How would one try to use OOP to solve this. Would it make sense to have 6 different subclasses of the main State class with an evaluate() method, and then in their respective methods, I have if else statements to check:

  • if left & right arg are wildcards, do something
  • if left is number, right is string, do something else
  • Repeat for all the valid combinations in each State subclass

This feels like the right direction, but it also feels like theres alot of duplicate logic (for example check if both args are wildcards, or both strings etc.) for all 6 subclasses. Then my thought is to abstract it abit more and make another subclass:

For each state subclass, I have stateWithTwoWildCards, statewithTwoString etc.

But I feel like this is going way overboard and over-engineering and being "too" specific (I get that this technically adheres tightly to SOLID, especially SRP and OCP concepts). Any thoughts on this?

lundi 19 septembre 2022

Correct way to respond from REST api calls + WebSockets?

On certain routes in my app, I have the current implementation at the moment.

API call -> do something -> error occurs -> return with proper error

API call -> do something -> no errors -> respond with 204 -> send WebSocket/PubSub notification with successful response + data

This approach allows me to notify anybody looking at the same page (like 2 people looking at the same order) of the status change, etc and if an error happens only the initiator sees it and deals with it.

Something about this feels wrong. Is there a more correct approach to achieve similar results?

Tracking money within marketplace

I am working on a Patreon-like project where subscribers pay money to creators and where the project is the intermediary through which the money flows. Each incoming payment is saved into the system as "money" entity that has the user who made it as the owner and information about the money account where that money "physically" exists. This money entity can be split an joined(with previous entity deleted) so every cent is always accounted for. Money can change ownership(when subscriber pays to creator) and can be withdrawn, by creators, which removes them from the system(deletes the entities representing them).

Problem I am facing is that I can easily track this virtual money within the system but when it comes to the actual money(sitting in a bank account or with a payment processor), specifically when transfer between accounts happens(ie. payment processor sends money into my bank account + there are various bank accounts for different currencies) I will incur losses. For example a fee for the payment processor for withdrawal into my bank account or between bank accounts in different banks. In other words, I will send $10 but receive $9. This is obviously a business expense, so it's fine from that point of view, but it is not ok since the virtual money no longer matches the real money. The transfer fee essentially "stole" someone's money. As an example, imagine that payment processor will send 10 000$ into my bank account. This can consist of hundreds of payments by the customers which I can track to the last cent and know who exactly owns what. And imagine all these customers will pay to creators so all this money will now belong to creators and for some reason all creators will withdraw the money so none should be left in the bank account. Now imagine that 10k transfer cost 1$ to the payment processor for withdrawal. So once I start paying off creators, the last creator will be short by 1$ real dollar. I have no way of tracking whose money was "stolen" by this fee.

Of course, I can track the fees and "charge" the bank account with this difference from the business account and write it off as business expense but then it means I introduce foreign real money into the system which is the not traceable with the virtual money.

In other words, real money transfer will most likely not be free and what is sent is not what will be received whereas virtual transfer(within my system) is fee-free and will never "lose" money.

So I wonder how to solve this problem of matching real money with virtual money in this scenario?

I could not care about where the physical money is and simply know it is in one of my accounts or payment processors' accounts but then I could easily have insufficient funds on bank account from where withdrawals are made and I would lost track of whose money is on which account. So the virtual money would be a mere aggregate of real money but with these fees they might not match.

Replace ordered if condition with design pattern

I've a legacy class with lots of if conditions, like:

public MyType methodWithIfs() {
  if (condition1) {
    return new MyType(param1);
  }

  if (condition2) {
    return new MyType(param2);
  }
  ....
}

Every if condition returns a type of MyType.

Also there is a order in which these conditions are mentioned. Two conditions can be true but only first that matched the criteria should be executed based on order.

I was thinking of replacing these conditions with Conditional Dispatcher with Command design pattern

Since there is an order to be maintained, instead of using HashMap<Boolean, MyType>, I was thinking of using LinkedHashMap<Boolean, MyType>.

But this seems dodgy. Is there any cleaner way I can replace these conditions?

Thanks!

how to force the children method arguments to extend specific class for multiple methods in java

I have an interface:

public interface Parent{
  Integer method1(Payment payment);
  Integer method2(Invoice invoice, Payment payment);
}

And I have multiple kinds of classes that extends Payment and Invoice class, let's say PaymentType1, InvoiceType1 and PaymentType2, InvoiceType2 are my children classes of Payment and Invoice.

Now, I want to create two classes that extend Parent in a way to force child classes to just use the extended class of Payment and Invoice. For example something like this:

First:

public class ChildType1 extends Parent{
  public Integer method1(PaymentType1 payment){...}
  public Integer method2(InvoiceType1 invoice, PaymentType1 payment){...}
}

Second:

public class Child2 extends Parent{
  public Integer method1(PaymentType2 payment){...}
  public Integer method2(InvoiceType2 invoice, PaymentType2 payment){...}
}

what kinds of solutions can I use to resolve it?

dimanche 18 septembre 2022

Where to write the common logic in Java Strategy design pattern?

This is related to Java Strategy design pattern.

In Strategy pattern, we create objects which represent various strategies and a context object whose behavior varies as per its strategy object.

I have common code logic to be executed for all the strategies which is have implemented using Java Strategy design pattern. Which is the right place to write this common logics(something like validations and other stuffs).

pattern moving in java [closed]

How could you print a pyramid pattern that keeps printing repeatedly such that the viewer feels as if the pattern is moving towards the end of the console screen could you please help me with this problem?

Why use provider as a closure if you can just pass an argument?

I'm wondering why ios devs use closure to pass single value if we can just pass the value itself? I've some doubts but I need some clear reasoning on why do it? I've seen it used commonly as providers. Here is an example

func navigate(_ property: Int, navProvider: (() -> UINavigationController)) {
  let vc = MyVC()
  vc.property = property

  let navController = navProvider()
  navController.push(vc)
}

what will happen if we changed this code to the below?

func navigate(_ property: Int, navController: UINavigationController) {
  let vc = MyVC()
  vc.property = property

  navController.push(vc)
}

Thanks!

How to dynamically add functions to typescript interface and its implementation?

I am working on a typescript package where users can extend its functionality by adding new features (actions) and the implementation for that feature.

//IActions.ts -----------
export interface IActions {
  doSomething1(options?: Options1): Person;
  doSomething2(): Person;
  finallyDo(): Results;
  /*package user can extend this actions in their own files
    without modifying source files.*/

}

//Person.ts -----------
export default class Person implements IActions {
  actionLog: Log[];
  constructor(config?: PersonConfig) {
    //...
  }
  
  doSomething1(options?: Options1): Person {
    //actionLog.push...
    //...
    return this;
  }

  doSomething2(): Person {
    //actionLog.push...
    //...
    return this;
  }
  
  /*package user can extend this actions with their implantation
    in their own files without modifying source files.*/

  finallyDo(): Results {
    //...
  }
}

//PersonBuilder.ts -----------
interface PersonBuilder{
  createPerson: (config?: PersonConfig) => IActions;
}

export const personBuilder: PersonBuilder = {
  createPerson: (config?: PersonConfig) => {
    return new Person(config);
  },
};

//TestPersonBuilder.ts -----------
import personBuilder from 'person-builder-package';

const person = personBuilder.createPerson({...});
const result = await person
      .doSomething1(..)
      .doSomething2(..)
      .doSomething1(..)
      //package user can call their function with Type Annotations.
      .finallyDo();
  1. looking for a clean way to add new features (actions), something like 'Extension' method in c# but with ability to mock/test interface implementation.
  2. any similar design pattern that i can look into.
  3. user can build their own packages like plugins to extend this package.

Thanks.

samedi 17 septembre 2022

What is the best practice for [Testing] in no-live env without live env resources?

Let me explain this question in detail.

Background

Normally, we develop service/feature/system in no-live network and test the code also in no-live network. However, sometimes there are some dependencies which need to be accessed through live network. But it's not good to test the code in the live network directly since it may affect the online services.

Question

What is the best practice to solve such headache? (If some dependencies only can be accessed from live env)

Notes

in live network, we may have liveish env and live env

can iPad run frontend and backend

Let's say one builds an iPad app with the following requirements:

  • multiple iPads must be able to have the same state,
  • one of the iPads will always be unused by humans and simply connected to a large screen
  • Some basic data must be stored for export later,
  • iPads may be on the same network

Of course, most developers would use the cloud as the backend location but I p am thinking that one could possibly run the backend web server on the iPad connected to a screen. So, this iPad would be running two things: the app and the web server app. Is this possible? Assume the load is very light.

vendredi 16 septembre 2022

Please help solve this user input star pattern problem

user input pattern program problem

Plz help to solve this problem which you can find in this image there is 3 problems of same kind.

Extending 3rd party library in Python

I would like to extend Python Kubernetes client and add my own methods to some of its classes.

The way I thought it can be done is to create a wrapper library, which would load Kubernetes client and "monkey path it" by adding my own methods to the classes from Kubernetes client. So, that new wrapper library will provide exact same functionality as Kubernetes client + my own custom methods for some of the classes that Kubernetes client provides.

What would be a good way to do that? It would be great to have some examples as well.

Why the Class Adapter Design Pattern Can't Use an Interface Instead of Multiple Inheritance?

I've recently learned the Class Adapter pattern. In order to implement it, the language used must support multiple inheritance since the adapter class must inherit two classes, the Target, and the Adaptee. So in a language like Java, it could not be done.

But why couldn't it use an interface Target instead of a class Target? More inline with the Object Adapter pattern as well. Just switching from object composition (Adapter having the Adaptee) to single inheritance (Adapter inheriting the Adaptee). By using an interface, I don't see the design difference, and as a result, the pattern can be used in Java.

Link to object adapter and class adapter class diagram

Class Names and Design patterns

today I came across some weird case when thinking about naming my classes and using the right desing-patterns.

I was curious how you solve this?

So the situation is:

I got some views in general like: View-1, View-2, View-3 Each view got attributes like: mode and readonly. Mode can be "edit" or "show" and readonly is a boolean. So for each View I had following example data:

View 1 - edit - true View 1 - edit - false View 1 - show - true View 1 - show - false

Now I could assign a View to a WorkflowStep.. and this works fine right now. A WorkflowStep can have: buttons, views, actions and roles (in this case we just talk about the views).

The problem in this solution is.. that if I have more than one View, it gets a bit messy for the user, because he can choose from:

View 1 - edit - true View 1 - edit - false View 1 - show - true View 1 - show - false View 2 - edit - true View 2 - edit - false View 2 - show - true View 2 - show - false

etc.

As I'm developing in Laravel I used Polymorphic relationship with a table called: workflowstepable. So I could assign a view to a workflow step, and the workflowstepable-table looked like: workflow_step_id, workflowstepable_id, workflowstepable_type 1 | 1 | App\View

As this was a solution that has grown with the project.. i thought about a redesign. Right now the User has to choose from 8 views to drag and drop into a workflowstep. I would like to only show 2 views (View1, View2) to the User.. now he can drag and drop the view into a workflowstep.. and add further information like mode and readonly to only this specific ViewItem dropped into the Workflowstep.

I thought it would be better to split into following classes:

View: id, name, description

ViewItem: id, view_id, workflowstep_id, mode, readonly

WorkflowStep: id, order, etc.

So View would hold Views in general, like View1, View2 .. and ViewItem would bind the View to the WorkflowStep (1:1) and hold some more information like: mode, readonly.

Would ViewItem be a good name?

I would like to know if this is a common pattern, or if I'm missing something.

Thank you in advance

Create a convenience decorator to generate a Controller from a function using BeanPostProcessor?

I'm looking to write a decorator that takes a very simple function and wraps it inside a controller.

@AutoGetMapping("/users/{id}")
    public ResponseEntity<User> getById(@PathVariable long id) {
        Optional<User> user = userService.getById(id);
        if (user.isPresent()) {
            return new ResponseEntity<>(user.get(), HttpStatus.OK);
        } else {
            throw new RecordNotFoundException();
        }
    }

gets transformed to

@RestController
public class UserController {
 
    @Autowired
    UserService userService;
 
    @GetMapping("users")
    public ResponseEntity<List<User>> getAll() {
        return new ResponseEntity<>(userService.getAll(), HttpStatus.OK);
    }
 
    @GetMapping("users/{id}")
    public ResponseEntity<User> getById(@PathVariable long id) {
        Optional<User> user = userService.getById(id);
        if (user.isPresent()) {
            return new ResponseEntity<>(user.get(), HttpStatus.OK);
        } else {
            throw new RecordNotFoundException();
        }
    }
}

(maybe even the service layers).

I'm just looking for a place to start. I think im making a mistake in trying to use BeanPostProcessor and BeanDefinitionRegistryPostProcessor to do this. Can someone point me in the right direction on how to start doing this ?

How to design table to store the value without proper mapping

I am having below two table. T1_CATEGORIES table is preloaded with data and I know the categories name.

enter image description here

My application is going to Consume some API and in API will get the name in response which is not same as Table 1 categories name. Manually i know which name is mapped to T1_CATEGORIES name. e.g,

enter image description here

So from API i will get the autoloan and i want to insert that in to T2_SUBID_CATEGORIES table. I am facing issue how i will get the T1_CATEGORIES_ID from table T1. How can i map this so my T2_SUBID_CATEGORIES will contains the data as below,

enter image description here

Can you please help me to design this. I don't want to handle it in my java code. Any suggestion/approach must be apricated. Thanks

jeudi 15 septembre 2022

Make Bulk Requests API Client Programming Pattern / Design

I am writing an API client for a REST API that allows for requests the be batched together in and send as one request

I am struggling to figure out how to structure the client. I've come up with two designs so far (pseudo Python code):

  1. Async Method

    When calls to the api are made (make_api_request), the method waits for the bulk request to be made. Once the bulk request is made by calling the resolve coroutine, the request coroutine releases control back to he make_api_request method which processes the response for that specific request and returns it

    import asyncio 
    
    class FakeAPIClient:
        def __init__(self):
            """
            """
            pass
    
        async def make_api_request(self):
            """
            returns response after request is made 
            """
            resp = await self.request()
            #response processing 
            return resp 
    
    
        async def request(self):
            """
            I block until the bulk request is made 
            Once it is make, I return the response from the single request 
            """
            return "RESPONSE AFTER DONE BLOCKING "
    
    
        async def resolve(self):
            """
            Make the bulk request and release the make_api_request calls and return the assocaited responses 
            """
            return None
    
    
    async def example():
        api = FakeAPIClient()
    
        future1 = api.make_api_request()
        future2 = api.make_api_request()
        future3 = api.make_api_request()
    
        #3 requests are sent in bulk
    
        response1, response2, response3, _ = asyncio.gather(
            future1,
            future2, 
            future3, 
            api.resolve()
        )
    
    
    asyncio.run(example())
    
  2. Lookup method

    When calls to the api are made (make_api_request), a lookup ID is returned and the request is put into storage. When the resolve method is called, the bulk request is called, the requests in storage are sent as a bulk request and an object is returned that can be used to find the lookup id's corresponding response.

    class FakeAPIClient:
        def __init__(self):
            pass
    
        def make_api_request(self):
            """
            adds request to a queue of requests that will be resolved when resolve method is called
            also provide a callback for post request processing  
    
            returns a unique id of the request
            """
            return "UNIQUE ID"
    
    
        def resolve(self):
            """
            makes the bulk request 
            takes the responses and associates them with the request id 
            calls the callback associated with the response for post request processing 
    
            returns an object with a method that returns the responses when provided the request id 
            """
            return "RESPONSE LOOKUP"
    
    
    
    api = FakeAPIClient()
    
    lookup_id1 = api.make_api_request()
    lookup_id2 = api.make_api_request()
    lookup_id3 = api.make_api_request()
    
    lookup_object = api.resolve()
    
    response1 = lookup_object.get(lookup_id1)
    response2 = lookup_object.get(lookup_id2)
    response3 = lookup_object.get(lookup_id3)
    

I don't really love either of these solutions, but I can't think of any alternatives. I'd assume there are known patterns for solving this problem, what are they?

mercredi 14 septembre 2022

How to implement the GET request using ServiceLocatorFactoryBean ( Factory Method design Pattern)

I thank you ahead for your time to read my request. I'm new to the Spring Service Locator Factory Method design Pattern and I don't understand the approach behind it. However I followed a turtorial and have been able to implement the Post request for my user registratio spring maven application. My src/main/java folder cointains this five packages:

  1. Config
  2. Controller
  3. Model
  4. Registry
  5. Service

The Config package is to centralize the creation of users and its java class is as bellow: package com.nidservices.yekoregistration.config;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ServiceLocatorFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.nidservices.yekoregistration.registry.ServiceRegistry;

@Configuration
public class UserConfig {
  @Bean
  public FactoryBean<?> factoryBean() {
      final ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
      bean.setServiceLocatorInterface(ServiceRegistry.class);
    return bean;
  }
}

The Registry package is to adapt the service base on the type of entity to create and is as bellow:

package com.nidservices.yekoregistration.registry;

public interface AdapterService<T> {
  public void process(T request);
}



 package com.nidservices.yekoregistration.registry;

public interface ServiceRegistry {
  public <T> AdapterService<T> getService(String serviceName);
}

The Service package contains the different types of entity that inherit the User Model and the User Model is as bellow:

public class User implements Serializable {
    private UUID id;
    private String userIdentifier;
    private String userType;
    
    
    public String getUserIdentifier() {
        return userIdentifier;
    }
    public void setUserIdentifier(String userIdentifier) {
        this.userIdentifier = userIdentifier;
    }
    public String getUserType() {
        return userType;
    }
    public void setUserType(String userType) {
        this.userType = userType;
    }
    
    
    @Override
    public String toString() {
        return "User [userIdentifier=" + userIdentifier + ", UserType=" + userType + "]";
        
    }

}

And the Post Request defined in the Controller is as bellow:

package com.nidservices.yekoregistration.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.nidservices.yekoregistration.model.User;
import com.nidservices.yekoregistration.registry.ServiceRegistry;


@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private ServiceRegistry serviceRegistry;
    
    @PostMapping
    public void processStudentDetails(@RequestBody User user) {
        serviceRegistry.getService(user.getUserType()).process(user);
    }
}

Now I'm struggling to make the GET Request to get all created users. I'm used with the DAO design pattern and very new with the concept behind ServiceLocatorFactoryBean. I appreciate your help to help me implement my CRUD endpoints using ServiceLocatorFactoryBean. Thanks in advance.

Is it possible to make methods behave based on the caller without checking each possibility?

I have a small backend to get data from an API. I'm using only one class to manage multiple API endpoints (JWT token and 2 other endpoints) and good old Curl to build the requests. Currently i'm using a private method (buildCurl) that behaves based on another internal method that calls it -currently three, corresponding to the endpoints-. the callers pass their name to buildCurl so it can check and build the necessary request accordingly.

It works fine but i feel like i'm doing something fundamentally wrong from the design perspective or there are more elegant solutions to this, specially if the number of endpoints increases.

What i can see: my first guess would be to make one class for each endpoint, but that would generate a lot of code duplication. Another one would be to make my current class a parent class of my endpoints (inheritance) and make buildCurl polymorphic (but one class for each endpoint would still be necessary).

Here's the code:

class ApiRequestManager {
...
  // One endpoint
  public function getDataCpf(string $cpf) {
    ...
    // Get the curl resource. Give the current function/method name to buildCurl.
    $curl = $this->buildCurl($authString, $requestParam, __FUNCTION__);
    ...
    return $this->getResponse($curl, ...);
  }
  private function buildCurl($authString, $parameters, $methodName) {
    // Options common to all cases
    $options = [
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_FOLLOWLOCATION => true,
      ...
    ];

    if($methodName === 'getToken') {
      $options[CURLOPT_URL] = $this->apiConfig['serverUrl'] . $this->apiConfig['authTokenUrl'];
      ...
    } elseif($methodName === 'getDataCpf') {
      ...
    } elseif(...) {
      ...
    }
  }
  ...
}

Any suggestions?