#Are there even any use cases of manual interfaces?

1 messages · Page 1 of 1 (latest)

fervent kelp
#

Correct me if I’m wrong please. Interfaces are the guidelines to a class what methods to include but not actually describing what those methods do.

I see interfaces are widely used in Java libraries and Spring Boot JPA etc. But after practicing for a while I have never manually added an interface except EntityRepository extends JpaRepository. I’d like you to know what are the use cases of manual interfaces?

weary cargoBOT
#

<@&987246399047479336> please have a look, thanks.

#

Here is an AI assisted attempt to answer your question 🤖. Maybe it helps! In any case, a human is on the way 👍. To continue talking to the AI, you can use </chatgpt:1108714622413963314>.

#
TJ-Bot
Correct me if I’m wrong please. Interfaces are the guidelines to a class what methods to include but not actually describing what those methods do. I see interfaces are widely used in Java libraries and Spring Boot JPA etc. But after practicing for a whil

Yes, there are use cases for manual interfaces in Java. An interface in Java is a contract that specifies a set of methods that a class must implement. While it does not provide the implementation of these methods, it defines the structure and behavior that any implementing class must adhere to.

Manual interfaces can be useful in scenarios where you want to enforce a specific set of methods in multiple classes without providing any default functionality. This allows for better code organization, modularity, and flexibility in your program design.

For example, if you have a group of classes that need to perform similar actions but with different implementations, you can create a manual interface specifying the required methods. Each class can then implement this interface and provide its own implementation details while still adhering to the contract defined by the interface.

In summary, manual interfaces in Java serve as a blueprint for classes to follow by defining the method signatures without specifying their implementations. They can be used to enforce consistency among different classes and promote code reusability and maintainability in your software projects.

hushed brook
#

u might want to read this:

weary cargoBOT
#

An interface defines a set of method signatures, as contract. It can greatly increase code modularity. Often, interfaces are property-driven.

interface CanWalk {
  void walkLeft();
  void walkRight();
}

There is no method body. So if a class implements CanWalk, he makes the promise to offer those methods:

class Player implements CanWalk {
  int x;

  @Override
  void walkLeft() {
    x--;
  }

  @Override
  void walkRight() {
    x++;
  }
}

Someone could now demand a CanWalk instance and use the methods:

class Mover {
  static void moveAround(CanWalk canWalk) {
    for (int i = 0; i < 10; i++) {
      canWalk.walkRight();
    }
    canWalk.walkLeft();
    canWalk.walkRight();
  }
}

Note that the moveAround accepts everything that can walk.

Mover.moveAround(player);

We could also give it a Dog, as long as it implements CanWalk.

You have two options to create instances of interfaces:

  1. Create a class that implements the interface, like Player
  2. Use an anonymous class:
CanWalk canWalk = new CanWalk() {
  @Override
  void walkLeft() {
    System.out.println("Walking left");
  }

  @Override
  void walkRight() {
    System.out.println("Walking right");
  }
};

An interface that only offers one method is called a functional interface:

@FunctionalInterface
interface IntOperation {
  int operate(int a, int b);
}

You have two additional options to create instances of it:
3. Lambda expression

IntOperation operation = (a, b) -> a * b;
System.out.println(operation.operate(5, 3)); // Prints 15
  1. Method reference
// Method in MathUtil
static int multiply(int a, int b) {
  return a * b;
}

// Use it as
IntOperation operation = MathUtil::multiply;
System.out.println(operation.operate(5, 3)); // Prints 15
tired totem
fervent kelp
#

I didn’t meet any scenario to use manual interfaces in my basic java practice projects

#

In my area tho almost all projects use node backend except for rly big enterprises so when i try to contribute to those projects i rarely meet java, I need to improve more on java i guess

tired totem
#

its an interesting thing to explain because you aren't exactly wrong to note that in web development you have less need to interfaces/polymorphism than in other kinds of programs

#

but there are interfaces around

#

like if you ever use .stream()

fervent kelp
#

Then where does java shine the most?

tired totem
fervent kelp
#

Only in enterprises?

tired totem
#

so here's a use of interfaces:

fervent kelp
tired totem
#

right now at work we are using a website called persona

#

and when we run automated tests we don't want to actually make calls to them by accident

#

so

#
interface PersonaClient {
    CreateInquiryResult createInquiry(CreateInquiryArgs args);
}

class MockPersonaClient implements PersonaClient {
    MockPersonaClient() {}

    @Override
    public CreateInquiryResult createInquiry(CreateInquiryArgs args) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

class RealPersonaClient implements PersonaClient {
    RealPersonaClient(String baseUrl, String apiKey) {

    }

    // ...
}
#

i wrote java here, but we are writing typescript

#

and we are manually implementing an interface there

#

this is actually my job for today

#
import { Env, getEnv } from 'functions/env';
import axios, { Axios } from 'axios';
import { identity } from 'lodash';
import { logResponseError, sanitizeError } from 'functions/utils/axiosHelpers';

type CreateInquiryArgs = any;

type CreateInquiryResult = any;

export interface IPersonaClient {
  createInquiry(args: CreateInquiryArgs): Promise<CreateInquiryResult>;
}

export class PersonaClient implements IPersonaClient {
  private readonly client: Axios;

  constructor(baseUrl: string, personaApiKey: string) {
    this.client = axios.create({
      baseURL: baseUrl,
      headers: {
        Authorization: `Bearer ${personaApiKey}`,
        'Content-Type': 'application/json',
        'Key-Inflection': 'snake',
      },
    });

    this.client.interceptors.response.use(identity, sanitizeError);
    this.client.interceptors.response.use(identity, logResponseError);
  }

  createInquiry(_args: CreateInquiryArgs): Promise<CreateInquiryResult> {
    throw new Error('Method not implemented.');
  }
}

export class MockPersonaClient implements IPersonaClient {
  createInquiry(_args: CreateInquiryArgs): Promise<CreateInquiryResult> {
    throw new Error('Method not implemented.');
  }
}

export const getClient = (): IPersonaClient => {
  if (getEnv() === Env.Test) {
    return new MockPersonaClient();
  }

  return new PersonaClient('', process.env.PERSONA_API_KEY!);
};

#

obv. going to narrow down those any's

#

but we would do a similar thing in java too

#

(with something smarter than getClient, but 🤷‍♂️ )

fervent kelp
hexed fjord
#

Indeed, once you start writing unit tests, you don't want the class under test to use the real implementation for it's (service) dependencies. So you make sure that the type of the dependency in the class under test is an interface, so you can swap it out with a mock for testing

fervent kelp
#

I haven’t tried testings yet maybe i understand later

tired totem
#

making software is about tradeoffs

fervent kelp
#

Yea that’s one of the problems for my learning rn, sometimes i want 100% dependency injection with loosely coupled as possible, and can’t progress that much

tired totem
#

you will always have coupling

#

you just need to pick where it will be

#

I would prefer dependency injecting, but theres a few factors making that

  1. Not super easy (because typescript)
  2. Not worth the effort (because we test as a deployed distributed system, less of the basic unit tests)
fervent kelp
#

I think i need to think abt my extents and degree between flexibility and modularity, sometimes i focus on modularity too much that progress is extremely slow

tired totem
#

focus on making the damn programs work

fervent kelp
#

Lol i am theoretically sunk

glad finch
#

refactoring is a skill that takes years to properly develop

#

Just make sure it works first

#

Then figure out what to improve

#

Then figure out how to get there in steps

fervent kelp
#

Refactoring in OOP is pretty new to me for now, i used to refactor my classmates’ node backend and oop is nothing like it

#

Even so i still make crapware with my skills lol

#

Btw abit off-topic, I am using Debian WSL and works very fine to me compared to windows dev env

#

Any pitfall to notice? I am fairly good at linux navigation, access, package control, net tools in cli

glad finch
#

stop taking the shotgun approach

#

focus

fervent kelp
tired totem
#

you'll figure it out eventually