Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Paulo
    @ptrecenti
    something like that
    public final class PgOrganizations implements Organizations {
    
        private final DataSource dataSource;
        private final Filter filteredBy;
        private final Object[] params;
    
        public PgOrganizations(DataSource dataSource) {
            this(
                    dataSource,
                    Filter.NONE
            );
        }
    
        public PgOrganizations(DataSource dataSource, Filter filteredBy, Object... params) {
            this.dataSource = dataSource;
            this.filteredBy = filteredBy;
            this.params = params;
        }
    
        @Override
        public Iterable<Organization> iterate() {
            try {
    
                final JdbcSession session = new JdbcSession(this.dataSource);
    
                session.sql(
                        String.format("SELECT id FROM organization %s", filteredBy.where)
                );
    
                for (Object param : params) {
                    session.set(param);
                }
    
                return session.select(
                        new ListOutcome<>(
                                (ListOutcome.Mapping<Organization>) rset -> new PgOrganization(
                                        dataSource,
                                        rset.getInt(1)
                                )
                        )
                );
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override
        public Organization add(OrganizationUrl url) {
            try {
                return new PgOrganization(
                        this.dataSource,
                        new JdbcSession(dataSource)
                                .sql("INSERT INTO organization (email) VALUES (?)")
                                .set(url.toString())
                                .update(new SingleOutcome<>(Long.class)).intValue()
                );
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    
        public enum Filter {
            NONE(""),
            BY_URL("where url = ?");
    
            private final String where;
    
            Filter(String where) {
                this.where = where;
            }
        }
    }
    goqp
    @goqp
    no this is going in the wrong direction
    you are creating a super object that is god-controlling all of the needed behavior in this problem.
    think about modelling
    Paulo
    @ptrecenti
    do you have any example about what do I need to re-think?
    goqp
    @goqp
    I will try and write one. Lets think about the problem space of a bit. Why do you need a list of people who only have a single email or is restricted?
    What is going on here that we are MODELLING?
    Paulo
    @ptrecenti
    I got your point
    the problem that I'm trying to solve is sometimes I need to find a person by email but the identity of the person is an int id like that
    @EqualsAndHashCode(of = "id")
    public final class PgPerson implements Person {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(PgPerson.class);
    
        private final DataSource dataSource;
        private final int id;
        private final Account account;
    
        public PgPerson(DataSource dataSource, int id) {
            this(
                    dataSource,
                    id,
                    new PgAccount(
                            dataSource,
                            id
                    )
            );
        }
    
        public PgPerson(DataSource dataSource, int id, Account account) {
            this.dataSource = dataSource;
            this.id = id;
            this.account = account;
        }
    
        @Override
        public int id() {
            return this.id;
        }
    
    
        @Override
        public void update(Name name) {
    
            LOGGER.debug(
                    "name: {}",
                    name.toString());
    
            try {
                new JdbcSession(this.dataSource)
                        .sql("update person set first=?, middle=?, last=? where id = ?")
                        .set(name.first())
                        .set(name.middle())
                        .set(name.last())
                        .set(this.id)
                        .execute();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override
        public Name name() {
            try {
                return new JdbcSession(this.dataSource)
                        .sql("select COALESCE(first,''), COALESCE(middle,''), COALESCE(last,'') from person where id = ?")
                        .set(this.id)
                        .select((Outcome<Name>) (rset, stmt) -> {
                            rset.next();
                            return new DefaultName(
                                    rset.getString(1),
                                    rset.getString(2),
                                    rset.getString(3)
                            );
                        });
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override
        public Account account() {
            return this.account;
        }
    
    }
    goqp
    @goqp
    right, could be actually we want to find a person by first name, last name, or combination of both of them too.
    Could be by organization.
    The list of attributes is pretty large.
    Paulo
    @ptrecenti
    in the case of email it's unique and could define the identity of the person, but not the name (first, last, soon) because many people can have the same last name and this will return to me a list of people
    but I really don't know how fit the requirement to filter by last name (for example) without do what I made in the people class to filter by last name without rewrite the iterate method or use filter like the organizations
    goqp
    @goqp
    what I am saying is finding a person by email is a special case of finding some subset of people by any criteria
    whats the difference? None.
    The fact that the email is a unique mapping to a person is irrelevant.
    See, if you are looking for a person you have to stick with the person object.
    But if you are looking for potentially more than you just need a list that sorts on any criteria you specify.

    Paulo
    @ptrecenti
    ok, how could I deal with the fact to do not load the entire database and apply this criteria without re-write the iterate method?
    goqp
    @goqp
    Wait, I think you have solved the problem but your objects are like machines, not models.
    You need to strip them down and repackage the code.
    Paulo
    @ptrecenti
    I've tried to create a strategy to do that but I thought that it's going to a wrong way too
    goqp
    @goqp
    It was because you had helper objects for filtering inside of your list object.
    that isn't right.
    First of all. The list of people is a thing that we are modelling. Right? So it has a coordinate to a real world target (the database), which as all of the needed information about this list.
    So, the coordinate is the sql that the databse will use to create a temporary file (the result set of the query), that will then be read by the people list object.
    Right?
    Paulo
    @ptrecenti
    ok
    goqp
    @goqp
    So then, you have a list called FilteredPeople. Can you make JUST that for a second?
    When you ask filteredPeople for his iterable, he will return you a static snapshot of his people at that point in time.
    this should be some kind of ArrayList of people that implements iterable<People>
    You could, of course, make a filteredPeople list that actually iterates over the people by going record by record, but this would be really unstable.
    Paulo
    @ptrecenti
    yes
    goqp
    @goqp
    FilteredPeople only promises to tell you what he knows at one time. He doesnt know that the people he is aware of may have been deleted in the interim before you tried to navigate to one of them.
    He doesnt care.
    Actually, the best way to do filteredPeople is like this:
    new CachedPeople (  
     new FilteredPeople (
      database db, 
      string criteria
      )
    );
    Paulo
    @ptrecenti
    ok fine this the same idea of a super object like the organizations class that I show to you
    but I got your point
    thank you very much @goqp you help me a lot I really appreciate your time
    :thumbsup:
    goqp
    @goqp
    Awesome! Is it all clear then on how to compose the vertical decorators for the people list, and when to just use a person object rather than a list of people?
    Paulo
    @ptrecenti
    The problem i think is the of my objects
    Yes is pretty clear to me
    goqp
    @goqp
    Ok excellent.
    Paulo
    @ptrecenti
    You really help me
    goqp
    @goqp
    Try this rule of thumb: if the object looks "cute" and tiny, then it is okay. If it looks like a complex machine with lots of gears and parts, something is wrong. Refactor into smaller objects.
    Thanks, very glad I did !
    Each object should be a lightweight model that is mostly made of "air". The air is the (imagined) space in the text file that you literally write the code. Make sense? Here is a visual representation: