you all say, object oriented programming is about encapsulation, data hiding. Let's given this example:
class Rectangle
{
private int a,b;
public function __construct(int a, int b)
{
this.a = a;
this.b = b;
}
int public function getA()
{
return a;
}
int public function getB()
{
return b;
}
}
var r = new Rectangle(3, 4);
var area = r.getA() * r.getB();
this is a bad code then, so let's refaktor:
class Rectangle
{
private int a,b;
public function __construct(int a, int b)
{
this.a = a;
this.b = b;
}
int public function getArea()
{
return a*b;
}
}
r = new Rectangle(3, 4);
area = r.getArea();
way better, data hiding is done and getArea is brought where it belongs to.
Ok then, here comes the Active Records:
class Record
{
private int ID;
private string username;
public function __constructor(int ID, string username)
{
this.ID = ID;
this.username = username;
}
int public function getID()
{
return ID;
}
string public function getUsername()
{
return username;
}
}
r = new Record(1, 'test');
dbEngine.save(r);
this is again bad, since all data is public. (altough Doctrine works this way)
But if I do that as Propel did:
class Record
{
private int ID;
private string username;
public function __constructor(int ID, string username)
{
this.ID = ID;
this.username = username;
}
public function save()
{
dbEngine.save([ID, username]);
}
}
r = new Record(1, 'test');
r.save();
this is also said bad, because Active Records are antipattern. Then when it's good or bad? When does an "act" (getArea, save) should be brought inside an object - and when does it act outsidely?
You can inject the dbEngine dependency in for your specific case, but this doesn't address your concern.
In general, what makes your code good is how easy it is to understand, and how close changes in intention are tied to changes in implementation.
The problem with revealing private internals are that you're exposing your inner values that programs which interface with your program may rely on (and make difficult to change later on). A record is basically a struct/dataclass - it represents a collection of values that goes together with some well-defined meaning. Without knowing the rest of the code I can't say if this specific class is like that, but if that's the case it would be okay to just make it a struct (all members public, no methods).
There aren't any catch-all rules that makes code 'good'. It's a continuous process of making mistakes or being inefficient, and analysing what code led or made more likely that problem. Code smells are just the result of lots of trial and error by others, and although very robust in most cases may sometimes be outdated and should be applied in the specific situation when they improve your code.
None of your examples are bad. They are just design choices. Dropping the accessors to a and b in the second example seems a step backwards to me. As to putting implementation dependent save code in the class definition, that would be bad if there were multiple types that all needed to define the save. There you would be better to define a parent class with the save function and then inheriting from that class. However, if it’s just you writing code and there is just that one class it doesn’t matter.
Good that you are thinking about what makes good code. As a general rule, good code is code that works and which you can return to in 6 months and modify easily in the future. If you have a group of developers then of course provide accessors.
Another aspect of good code is having unit tests. If you change something and the unit tests pass you’ve done your job. If someone is using internals they should write a unit test that will signal a change that would break their code.
Related
I'm trying to #Test a Service class but there are several get() methods that I don't know how to test. I would need to know how to collect the data that is necessary or at least how to test the rest of the methods of the TokenHelper class.
This is the Session class:
public class SessionData {
public static final String KEY = "session_data";
private Integer id;
private String email;
private String fullName;
private List<Role> role;
private Boolean tempSession;
private int permissionsMask = 0;
private String avatar;
public boolean hasAnyRole(Role... roles) {
for (Role r : roles) {
if (this.role.contains(r)) {
return true;
}
}
return false;
}
}
This is the TokenHelper class:
public class TokenHelper {
public String generate(SessionData tokenData, long expirationInHours) {
return Jwts.builder()
.claim(SessionData.KEY, tokenData)
.setIssuedAt(Date.from(Instant.now()))
.setExpiration(Date.from(Instant.now().plus(expirationInHours, ChronoUnit.HOURS)))
.signWith(SignatureAlgorithm.HS256, TextCodec.BASE64.encode(secret))
.compact();
}
public UserGoogle getTokenDataFromGoogleToken(String token) throws InvalidTokenException {
try {
int i = token.lastIndexOf('.');
String withoutSignature = token.substring(0, i + 1);
Claims claims = Jwts.parser().parseClaimsJwt(withoutSignature).getBody();
return UserGoogle.builder()
.email(claims.get(UserGoogle.KEY_EMAIL).toString())
.firstName(claims.get(UserGoogle.KEY_FIST_NAME).toString())
.lastName(claims.get(UserGoogle.KEY_LAST_NAME).toString()).build();
} catch (ExpiredJwtException | MalformedJwtException | SignatureException | IllegalArgumentException ex) {
log.error(ERROR_TOKEN, ex.toString());
throw new InvalidTokenException();
}
}
}
This is my #Test:
#Test
void googleTokenHelperTest() throws InvalidTokenException {
TokenHelper obj1 = BeanBuilder.builder(TokenHelper.class).createRandomBean();
String mailGoogle = "google#prueba.com";
String firstGoogle = "Nombre";
String lastGoogle = "Apellido";
Map<String, Object> pruebaGoogle = new HashMap<String, Object>();
List<String> info = new ArrayList<String>();
info.add(firstGoogle);
info.add(lastGoogle);
pruebaGoogle.put(mailGoogle, info);
UserGoogle expectedUser = UserGoogle.builder().email(mailGoogle).firstName(firstGoogle).lastName(lastGoogle).build();
String myTestToken = pruebaGoogle.toString();
UserGoogle actualUser = obj1.getTokenDataFromGoogleToken(myTestToken);
assertEquals(actualUser, expectedUser);
}
I have created some variables to form a user, but I need to build them with a map to generate the token with the help of the generate () method. I need to know how to join those three variables and pass them to the generate () method, and then pass the result variable to the google method to generate the new user.
Edit: After clarification by OP the topic of the question changed.
Your problem arises from a flawed Object-Orientation-Design. For example, your SessionData implicitly holds a User by having String-fields relevant to a User among fields relevant to a Session. This overlapping makes it hard to test your code, because in order to test your Token-Generation for some User data, you need a Session object, which introduces additional data and dependencies.
That is one major reason, why it's difficult for you, to get a token from your three input values.
You want to test getTokenDataFromGoogleToken(String token). First thing you need to know is, what a valid Token-String will look like.
Next, you will need to mock your Claims claims object in one of two ways:
Mockito.mock it using Mockito to return the necessary Strings when claims.get() is called.
Mockito.mock your Jwts.parser().parseClaimsJwt(withoutSignature).getBody() to return a Claims object that serves your testing purpose.
Since the signature of your token will be irrelevant to your tested method, just focus on the substring before the .-Separator, i.e. the part after . in your token string can be any string you like.
If you want to test generate(SessionData, long) you need to supply a SessionData Object and a long value. After that you assertEquals the String as necessary. However, currently your code does not imply that your get is in any way related to your generate. This is, because you just handle Strings. A better design would be to have e.g. a User, Session and Token-classes, which would also make it easier to test your application and units.
A Test for your getToken method looks like the following, you just have to replace ... with your test data.
#Test
void givenGoogleToken_whenTokenHelperGeneratesUserFromToken_UserOk() {
TokenHelper helper = new TokenHelper();
String myTestToken = ...; //
UserGoogle expectedUser = ... // generate the UserGoogle Object you expect to obtain from your TokenHelper class
UserGoogle actualUser = helper.getTokenDataFromGoogleToken(myTestToken);
assertEquals(actualUser, expectedUser);
}
Test generally follow a given-when-then structure. Given some precondition, when some action is performed, then some result is returned/behaviour observed. When implemented very formally, this is called BDD (Behaviour Driven Development), but even when not practicing BDD, tests still generally follow that pattern.
In this case, I would suggest the tests be something like:
Given some data exists in the service threaddata
when I call get
then I get back the expected value
In the scenario above, the given part probably consists of setting some data on the service, the when is invoking get and the then is asserting that it's the expected value.
And I'd encourage you to consider the various scenarios. E.g what happens if the data isn't there? what happens if it's not the class the consumer asks for? Is the map case-sensitive? etc...
Code sample for the initial instance (I'm not sure what BeanBuilder is here, so I've omitted it):
#Test
public void testCurrentThreadServiceReturnsExpectedValue() {
final String key = "TEST KEY";
final String value = "TEST VALUE";
//Initialize System Under Test
CurrentThreadService sut = new CurrentThreadService();
//Given - precondition
sut.set(key, value);
//When - retrieve value
String observedValue = sut.get(key, String.class);
//Then - value is as expected
assertEquals(value, observedValue);
}
EDIT TO ADD It's always great to see someone get into unit testing, so if you have any follow ups, please ask I'm happy to help. The confidence one derives from well tested code is a great thing for software devs.
I'm new to GraphQL and I'm currently implementing a GraphQL API into an established Java code, using GraphQL-SPQR and I'm running into a couple issues when it comes extracting data from hierarchical classes.
The issues that I am running into are as follows.
Firstly I don't if there is an easy way to get all the data associated with a returned node. If there is, this would be most useful for my more complex classes.
Secondly when a method returns an abstract class, I only seem able to request the variables on the abstract class. I'm sure this should be possible I am just hitting my head against a wall.
As a simple example
public abstract class Animal {
private String name;
private int age;
// Constructor
#GraphQLQuery(name = "name")
public String getName() {
return name;
}
// Age getter
}
public class Dog extends Animal {
private String favouriteFood;
// Constructor
#GraphQLQuery(name = "favouriteFood")
public String getFavouriteFood() {
return favouriteFood;
}
}
public class Database {
#GraphQLQuery(name = "getanimal")
public Animal getAnimal(#GraphQLArgument(name = "animalname") String animalname) {
return database.get(name);
}
}
So in my first question what I am currently querying is.
"{animalname(name: \"Daisy\") {name age}}"
This works fine as expected. If you imagine the class however had 10 variables I would like to merely be able to write the equivalent of the following without having to look them up.
"{node(name: \"Daisy\") {ALL}}"
Is this possible?
In terms of my second question.
The follow query, throws an error ('Field 'favouriteFood' in type 'Animal' is undefined')
"{animalname(name: \"Bones\") {name age favouriteFood}}"
likewise (reading Inline Fragments of https://graphql.org/learn/queries/)
"{animalname(name: \"Bones\") {name age ... on Dog{favouriteFood}}}"
throws an error Unknown type Dog
This is annoying as I have a number of sub classes which could be returned and may require handling in different fashions. I think I can understand why this is occuring as GraphQL has no knowledge as to what the true class is, only the super class I have returned. However I'm wondering if there is a way to fix this.
Ultimately while I can get past both these issues by simply serialising all the data to JSON and sending it back, it kind of gets rid of the point of GraphQL and I would rather find an alternate solution.
Thank you for any response.
Apologies if these are basic questions.
Answering my own question to help anyone else who has this issue.
The abstract class needs to have #GraphQLInterface included, as shown below
#GraphQLInterface(name = "Animal ", implementationAutoDiscovery = true)
public abstract class Animal {
private String name;
private int age;
// Constructor
#GraphQLQuery(name = "name")
public String getName() {
return name;
}
// Age getter
}
The following code was found after much solution and was created by the creator of SPQR. Effectively, when setting up your schema you need to declare an interface mapping strategy. The code below can be copied wholesale with only the "nodeQuery" variable being replaced with the service you are using to containing your "#GraphQLQuery" and "#GraphQLMutation" methods.
final GraphQLSchema schema = new GraphQLSchemaGenerator()
.withInterfaceMappingStrategy(new InterfaceMappingStrategy() {
#Override
public boolean supports(final AnnotatedType interfase) {
return interfase.isAnnotationPresent(GraphQLInterface.class);
}
#Override
public Collection<AnnotatedType> getInterfaces(final AnnotatedType type) {
Class clazz = ClassUtils.getRawType(type.getType());
final Set<AnnotatedType> interfaces = new HashSet<>();
do {
final AnnotatedType currentType = GenericTypeReflector.getExactSuperType(type, clazz);
if (supports(currentType)) {
interfaces.add(currentType);
}
Arrays.stream(clazz.getInterfaces())
.map(inter -> GenericTypeReflector.getExactSuperType(type, inter))
.filter(this::supports).forEach(interfaces::add);
} while ((clazz = clazz.getSuperclass()) != Object.class && clazz != null);
return interfaces;
}
}).withOperationsFromSingleton(nodeQuery)// register the service
.generate(); // done ;)
graphQL = new GraphQL.Builder(schema).build();
As this solution took some hunting, I'm going to start a blog soon with the other solutions I've stumbled on.
With regards to having a query that just returns all results. This is not possible in GraphQL. One workaround I might write is to have a endpoint that returns JSON of the entire object and the name of the object, then I can just use ObjectMapper to convert it back.
I hope this helps other people. I'm still looking into an answer for my first question and will update this post when I find one.
I am trying to get IZO-809 certification I was reading the OCA/OCP SE8 test book and a code really caught my attention.
The code gets me to this question.
I know consumer get a parameter and not return nothing and Supplier has not parameters and returns a value.
But this code is almost the same after the ->.
public class Pregunta24{
private final Object obj;
public Pregunta24(final Object obj){
this.obj = obj;
}
}
//Returns a Supplier
private final Supplier<Pregunta24>supplier = ()->new Pregunta24("HI");
//Returns a Consumer.
private final Consumer<Pregunta24>consumer = a->new Pregunta24(a);
Both codes work.
But if this code not work i know that consumer doesn't return nothing.
private final Consumer<String>consumerString = String::length
I know this not work because consumer doesn't return a value my question is in the supplier code and the consumer code the code is right after the -> mark but this time is considered return in fact a instance of the class.
My question is why sometimes Java complaints that is a return value and something not?
I mean this code.
private final Supplier<Pregunta24>supplier = ()->new Pregunta24("HI");
// I would think is returning a instance of the Pregunta24 class.
private final Consumer<Pregunts24>consumer = a->new Pregunta24(a);
Is returning the same after the -> but why in the consumer don't say the error.
incompatible types: bad return type in lambda expression
But if do this I do
final Consumer<String>consumerString = a->1;
I think the code after the -> is context inferred.
According to javadoc Consumer:
Represents an operation that accepts a single input argument and
returns no result.
Consumer<Pregunts24>consumer = a->new Pregunta24(a);
doesn't actually return anything. This basically is implementation of Consumer#accept method, which accepts an object of type T and has void as return type.
public void accept(Pregunta24 a) {
new Pregunta24(a);
}
You are not returning anything. Same thing with
Consumer<String>consumerString = String::length
public void accept(String a) {
a.length();
}
However
Consumer<String>consumerString = a->1;
is an invalid expression which is translated to something like this:
public void accept(String a) {
1;
}
In the system I'm currently working on, I'm following SRP (I think!) by separating the validation of domain business rules vs persistence constraints. Let's employ the overused customer example. Say a customer must have a valid zip code, street address and name to satisfy the system's business rules. Let's further say that the customer's selected user name must be unique across all customers, which I define as a persistence constraint. Please consider the following "not ready for production" pseudo code:
public interface IPersistenceValidator<T>
{
bool IsValidForPersistence(T domainObj, IList<ValidationError> validationErrors);
}
public interface IValidatable
{
bool IsValid(IList<ValidationError> validationErrors);
}
public class Customer : IValidatable
{
public bool IsValid(IList<ValidationError> validationErrors)
{
//check for business rule compliance
}
}
public class CustomerDao : IPersistenceValidator<Customer>
{
public bool IsValidForPersistence(Customer domainObj, IList<ValidationError> validationErrors)
{
//check for persistence constraint compliance (user name is unique)
}
public bool SaveCustomer(Customer customer)
{
//save customer
}
}
The classes defined above might get wired up into a service class as follows:
public class SaveCustomerService
{
private CustomerDao _customerDao;
public SaveCustomerService(CustomerDao customerDao)
{
_customerDao = customerDao;
}
public bool SaveCustomer(Customer customer)
{
IList<ValidationError> validationErrors = new List<ValidationError>();
if (customer.IsValid(validationErrors))
{
if (_customerDao.IsValidForPersistence(customer, validationErrors))
{
return _customerDao.SaveCustomer(customer);
}
else
{
return false;
}
}
else
{
return false;
}
}
}
My primary concern with this approach is that future consumers of CustomerDao must know to call IsValidForPersistence() before SaveCustomer(), otherwise invalid data gets persisted. I could create DB constraints to guard against this at the SQL levels, but that feels like a kludge.
It seems like IsValidForPersistence() should be moved into CustomerDao.SaveCustomer() but then I have to refactor the signature of SaveCustomer() to include references to the ValidationErrors class. Before I dive into that big of a refactoring, I wanted to get some feedback from others on common/preffered patterns for dealing with these issues.
Thanks
first check HERE if you want to solve your validation problem like;
public class Address {
#NotNull private String line1;
private String line2;
private String zip;
private String state;
#Length(max = 20)
#NotNull
private String country;
#Range(min = -2, max = 50, message = "Floor out of range")
public int floor;
...
}
anyway you must check username in database. You can customize your validation (like go and check DB for that is unique). Look at another links to detail.
Check hibernate validator
Check Using the Validator framework from jboss
You can read Validation In The Domain Layer partI, partII, this is not java but logic is important.
Say you have 5 or 6 variables in the model which a certain View is interested in, do you write different functions for each, such as
int a;
int b;
int c;
void setA( newA ) {
a = newA;
notifyAObservers();
}
void setB( newB ) {
b = newB;
notifyBObservers();
}
void setC( newC ) {
b = newC;
notifyCObservers();
}
Or do you just have one notify method and waste a little bit of CPU time
i.e. instead of notifyAObservers and notifyBObservers, you just have notifyObservers
I believe the traditional approach is to notify all observers, and let them handle it. This is because you don't know which observers are observing which variable(s) - you just know that they want to be notified when something changes. However, if you do know what observers are observing which variables, and performance is critical, then you might be able to do something like what you have.
In the traditional Observer pattern, the Observers implement an update() method that is called by the controller when a change happens. The Observables (the data model) would have a notifyObservers() method that iterates over the Observers and calls their update() method. Then, the Observers get whatever they need and the view updates.
Any time I have implemented the Observer pattern, however, I simply keep a list of observers and notify them all. That way, I only have one list of observers and the rest of the class as well as the different observers can all change without me making any changes to the observable class notification.
EDIT: I wrote my answer a few years ago. After reading it just now, I felt I needed to update it.
I believe the best approach is to notify all observers and let the views decide if they need to update themselves..
Each view will be able to verify the state of the model and act accordingly.
Additionally, the "args" could be used as a flag to indicate what has changed (the view may not wish to update itself for every little change).
That way, the model REALLY does not know how and what the view is displaying, they are decoupled.
A first implementation would look like this:
public class MyModelV1 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
notifyObservers();
}
public int getValue() {
return value;
}
}
public class MyViewV1 implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof MyModelV1) {
System.out.println(((MyModelV1) o).getValue());
}
}
}
The view simply checks the type of the observable received.
However, if the model has many attributes and triggers the view for many different scenarios, this simple check may refresh the view too often.
Another approach would be the following:
public class MyModelV2 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
notifyObservers("value");
}
public int getValue() {
return value;
}
}
public class MyViewV2 implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof MyModelV2 && "value".equals(arg)) {
System.out.println(((MyModelV2) o).getValue());
}
}
}
Here, the notification passes a qualifier, which lets the view decide more precisely when to refresh itself.
The view still needs to check and cast the Model, because there is no garantee that the arg "value" isn't notified by another model (and the cast would fail at runtime).
My personal favorite is something along those lines:
public class MyModelV3 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
Notification.MY_MODEL_VALUE_UPDATED.notifyObserver(this);
}
public int getValue() {
return value;
}
}
public class MyViewV3 implements Observer {
public void update(Observable o, Object arg) {
if (Notification.MY_MODEL_VALUE_UPDATED.equals(arg)) {
MyModelV3 model = Notification.MY_MODEL_VALUE_UPDATED.getModel(o);
System.out.println(model.getValue());
}
}
}
public class Notification<T extends Observable> {
public static final Notification<MyModelV3> MY_MODEL_VALUE_UPDATED = new Notification<MyModelV3>();
private Notification() {
}
public T getModel(Observable o) {
return (T) o;
}
public void notifyObserver(T observable){
observable.notifyObservers(this);
}
}
Here, the notification sends a strongly typed qualifier, which is bound to the Model.
The view is able to use the notification to retrieve a strongly typed model (instead of casting).
This is somewhere between an observer and an event bus..