Jak unikać i czy w ogóle unikać powtarzającego się kodu w bloku try/catch?

0

Zauważyłem, że moja klasa która zawiera w sobie CRUDowe operacje, w każdej metodzie powtarza jeden i ten sam blok try/catch gdzie tak naprawdę różni się tylko jedna linijka no i zwracany typ. Przykładowo, operacja zapisu wygląda w ten sposób:

public Integer save(T objectToSave) {

		Session session = null;
		Optional<T> optionalObject = null;
		Integer savedObjectID = 0;

		try {
			session = HibernateUtils.getSessionFactory().openSession();
			session.beginTransaction();
			savedObjectID = (Integer) session.save(objectToSave);
			session.getTransaction().commit();
		} catch (Exception sqlException) {
			if (session.getTransaction() != null) {
				session.getTransaction().rollback();
				sqlException.printStackTrace();
			}
		} finally {
			session.close();
		}

		return savedObjectID;
	}

Nie wiem czy w takim wypadku taki kod powinno się refaktoryzować? Jeśli tak to w jaki sposób? Wymyśliłem coś takiego, żeby stworzyć interfejs generyczny CRUDOperation który będzie zawierał w sobie metodę execute(Session session); i dla każdej operacji stworzyć klasę która będzie go implementowała. Stworzyłbym też klasę CRUDStrategy gdzie również byłaby metoda execute(CRUDOperation operation) w której zamieścił bym blok try/catch i tam wywoływał interesującą mnie operację. Wyglądałoby to mniej więcej tak:

public interface IOperations {	
	void excecute(Session session);
}
public class AddingOperation<T> implements IOperations{
	
	private T objectToSave;
	
	public AddingOperation(T objectToSave) {
		this.objectToSave = objectToSave;
	}

	@Override
	public void excecute(Session session) {
		session.save(objectToSave);	
	}
}

public class CRUDStrategy<T> {
	
	public void execute(IOperations operation) {

		Session session = null;
		Optional<T> optionalObject = null;
		Integer savedObjectID = 0;

		try {
			session = HibernateUtils.getSessionFactory().openSession();
			session.beginTransaction();
			operation.excecute(session);
			session.getTransaction().commit();
		} catch (Exception sqlException) {
			if (session.getTransaction() != null) {
				session.getTransaction().rollback();
				sqlException.printStackTrace();
			}
		} finally {
			session.close();
		}
	}

}

I miejsce wywołania:

CRUDStrategy<Quote> strategy = new CRUDStrategy<>();
		strategy.execute(new AddingOperation<Quote>(quote));

Czy takie rozwiązanie ma sens? Czy warto dla każdej operacji tworzyć nową klasę i później jej instancję żeby nie powtarzać tego bloku try/catch jak to było przed zmianą? No i zostaje jeszcze kwestia zwracanego typu. Dla zapisu jest przecież typ liczbowy ale dla operacji odczytu jest to obiekt. Jak sobie z tym poradzić albo czy w ogóle warto zaprzątać sobie tym głowę? Może lepiej zostawić tak jak było, z jedną klasą i powtarzającym się kodem?

1

Tego typu powtórzenie nie jest jeszcze jakoś straszne, ale faktycznie lekko "boli". Wydaje mi się, że to rozwiązanie co mówisz jest spoko, nawet sobie możesz zrobić z tego interface funkcyjny zrobić. Zrobiłbym natomiast dwie metody. Jedna która zwraca jakąś generyczną wartość i drugą która tylko wykonuje coś w bazie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1