Czy AI zabierze nam pracę?

Nie. A dlaczego? A pamiętacie powiedzonko „There is no cloud, it’s just someone else’s computer”. Dokładnie z tego samego powodu nie stracimy pracy.

Czy AI pomoże nam w pracy?

To zależy, jak będziemy ją wykorzystywać. Dużo zależy też od samych modeli.

Ale skąd te pytania i dlaczego ten tekst?

Ponieważ wpadłem na pewien pomysł. Pamiętacie program „BattleBots”? Drużyny budowaly roboty, a następnie rywalizowały w róznych konkurencjach. Na koniec roboty były wpuszczane na arenę, gdzie walczyły ze sobą. Mój pomysł jest trochę inny. Opiera się o założenie, że mając jakieś zadanie programistyczne do wykonania, które chcemy wysłać do AI, powinniśmy wysłać je do co najmniej dwóch róznych i w miarę niezaleznych modeli. Następnie porównać zaproponowane wyniki i wybrać lepszy.

Przykład

Mamy taki oto kod:

Listing 1. Przykładowy program

import io.vavr.control.Either;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.ResponseEntity;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiHelper {

	public static <L, R> ResponseEntity<?> asResponse(Either<ResponseEntity<L>, ResponseEntity<R>> result) {
		if (result.isRight()) {
			return result.get();
		}
		return result.getLeft();
	}
}

Zlecam trzem modelom następujące zadanie

Refactor the following code:

I tutaj kodzik z Listingu 1.

I porównuję wyniki

AI Assistant w IntelliJ

I see multiple areas where this code could be improved:

  1. Extract Distinct Behaviour to Functions: The asResponse() function can be more understandable if divided into two separate functions named isResponseRight() and getLeftResponse(). This will improve code readability and also make it more maintainable.
  2. Renaming: The generic types L and R do not convey any meaning. These should be renamed to LeftResponse and RightResponse respectively for better readability.
  3. Change Signature: Changing the signature of asResponse method to include meaningful names for parameters. Let’s incorporate these into the provided code:
import io.vavr.control.Either;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.ResponseEntity;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiHelper<T extends Throwable, R> {
    public static <LeftResponse, RightResponse> ResponseEntity<?> asResponse(Either<ResponseEntity<LeftResponse>, ResponseEntity<RightResponse>> eitherResult) {
        if (isResponseRight(eitherResult)) {
            return eitherResult.get();
        }
        return getLeftResponse(eitherResult);
    }

    private static <LeftResponse, RightResponse> boolean isResponseRight(Either<ResponseEntity<LeftResponse>, ResponseEntity<RightResponse>> eitherResult) {
        return eitherResult.isRight();
    }

    private static <LeftResponse> ResponseEntity<LeftResponse> getLeftResponse(Either<ResponseEntity<LeftResponse>, ?> eitherResult) {
        return eitherResult.getLeft();
    }
}

With these refactorings, the code is more obvious and easy to understand. When someone looks at the asResponse method, it’s immediately clear what the method does, and the helper functions isResponseRight and getLeftResponse clarify the internal logic of the function.

Chat GTP-4o

Here is the refactored code:

import io.vavr.control.Either;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.ResponseEntity;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiHelper {

   public static <L, R> ResponseEntity<?> asResponse(Either<ResponseEntity<L>, ResponseEntity<R>> result) {
       return result.isRight() ? result.get() : result.getLeft();
   }
}

Changes Made:

  1. Simplified Conditional Statement: The if-else condition has been replaced with a ternary operator for conciseness.
  2. Consistent Formatting: Ensured consistent use of indentation and line breaks.

This refactoring retains the original logic while making the code more concise and readable.

Copilot

Sure, here’s a refactored version of your code. I’ve made it more concise and added some comments for clarity:

import io.vavr.control.Either;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.ResponseEntity;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiHelper {

   // Method to convert Either to ResponseEntity
   public static <L, R> ResponseEntity<?> asResponse(Either<ResponseEntity<L>, ResponseEntity<R>> result) {
       return result.fold(left -> left, right -> right);
   }
}

Changes made:

  1. Simplified the method: Used fold method from Either to handle both left and right cases in a single line.
  2. Added a comment: To explain the purpose of the method.

Let me know if you need any further modifications or explanations!

Wnioski

Jak widać każdy z modeli zaproponował inne podejście. AI Assistant skupił się na ekstracji nowych metod, które zamykają „dot-train”. Wyczuwam tutaj inspirację Prawem DemeterW, ale doprowadzoną do skrajności. Chat GTP-4o poszedł w kierunku zamiany if-else w operator elvisowy, czyli uproszczenie kodu w oparciu o dostępne elementy języka. W końcu wykorzystał możliwości vavr i zasugerował jakąś szczątkową dokumentację.

Mając takie rozwiązania możemy zdefiniować naszą wersję kodu:

Listing 2. Przykładowy program po refaktoryzacji

import io.vavr.control.Either;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.ResponseEntity;

import static java.util.function.Function.identity;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiHelper {

	public static <L, R> ResponseEntity<?> asResponse(Either<ResponseEntity<L>, ResponseEntity<R>> result) {
		return result.fold(identity(), identity());
	}
}

Co wygląda już całkiem miło. Dodaliśmy Function.identity() do końcowego rozwiązania.

Powracając do pytań zadanych na początku. AI nie zabierze nam pracy, ale może ją ułatwić. Jednak, żeby tak się stało musimy znaleźć efektywną metodę pracy z kilkoma modelami na raz. To do programisty będzie należeć decyzja, które z proponowanych rozwiązań lepiej pasuje do szerszego kontekstu.

W przyszłości będę wrzucał inne porównania modeli, stąd „I” w tytule.