1. ?? ??: ?? ????? ???
?? ?????? ? ???? ????? ??? ???? ?? ???????? ?????. ?? ?? ????? ????? ??, ??, ?? ??? ?? ???? ??? ? ????. ??? ????? ??? ???? ?? ???? ???. ??? ??? ??? ? ??? ???? ??? ????
1.1 ?? ????
?? ?? ?? ??? ???? ????? ??????? ??? ???.
- 1?? : ?? ???? ?? ??? ?????.
- 2?? : ????? ??? ?? ????.
- 3?? : ?? ?? ????? ??? ?????.
?? ??? ??? ? ??? ???? ?? ?? ???? ???? ???? ??? ?? ??? ???. ???? ??? ?????? ??? ????? ?????.
1.2 ?? ???? ? ??
??? ??? ????? 2?? ?? ????? ???? ?? ????? ???? ?? ????. ??? ?? ?? ? ?? ??? ?????.
- ?? ?? ?? : ? ???? ???? ?? ???? ??? ??? ?? ??? ?????.
- ??? ?? : ???? ??? ???? ?? ????? ???? ?? ??? ???? ?????.
- ??? ??: ???? ???? ???? ?? ???? ????? ????? ? ??????.
2. Saga ??? ??? ???? ??
?? ?????? ????? ?? ???????? ?? ????? ??? ????. ?? ???? ????? ????? ?? ???? ??? ?? ?? ??? ????. 2?? ??? ??? ?? ????? ???? ?? ???? ?? ??? ?? ?? ??, ??? ?? ? ??? ??? ?? ??? ?? ??? ? ? ????.
Saga ??? ?? ??? ?? ??? ?????. Saga ??? ????? ?? ??? ????? ???? ?? ????? ??? ? ?? ? ?? ??? ??? ????? ????. ? ??? ??????? ?????? ?? ??? ????? ?? ???????. ??? ???? ???? ?? ??? ???? ?? ???? ??? ??? ???? ???? ??? ??? ??? ? ??? ???.
2.1 ?? ???? ??????
Saga ??? ????? ??? ???? ?? ????? ??????. ?? ??? ??? ????.
- ?? ???? : ????? ??? ? ???? ?? ?? ????? ?????. ?? ??, ?? ?? ????? ??? ???? ??, ?? ???? ??, ? ?? ??? ?? ??? ??? ? ????.
- ??? ?? ??? ??: ???? ?? ????? ??? ? ???? ????? ?? ??? ???? ??? ???? ???? ????. ?? ?? ??? ??? ? ?? ????? "PaymentCompleted" ???? ??? ? ????.
- ?? ?? ???: ???? ?? ???? ???? ???? ?? ???? ?? ????? ?????. ?? ??? ?? ??? ??? ??? ?????.
- ?? ?? : ??? ???? ?? ??? ?????. ??? ??? ?? ???? ??? ??? ????? ???????. ?? ??, ?? ? ?? ??? ???? ?? ??? ?? ?? ??? ???? ???.
2.2 ??? ??
?? ??? ???? ??? ?? ??? ??????? ? ??? ????.
2.2.1 ????
?????? ?? ?????? ????. ??, Saga? ??? ? ???? ???? ???? ?? ??? ??? ?? ??? ?? ??? ?????. ? ?? ??? ???? ?? ???? ????? ??? ? ????. ?? ??? ??? ????.
- ??? ?? ?? : ? ???? ?? ???? ??? ???? ?????. ?? ?? ?? ???? ??? ??? ? "PaymentCompleted" ???? ??????. ???? ???? ? ???? ???? ?? ???? ?? ?? ?????.
- ??? ?? : ?? ???? ?? ??? ? ???? ??? ???? ?? ??? ??? ??? ??? ???. ??? ?? ???? ? ?? ???? ????? ?? ???? ??? ?? ??? ??? ? ??? ??? ??? ?????.
- ?? ??: ???? ??? ??? ???? ?? ???? ??? ? ???, ?? ???? ?? ???? ?? ??? ???? ? ????. ?? ??, ?? ???? ??? ????? ? ?? ?? ?? ???? ??? ????? ?? ?? ???? "InventoryUpdateFailed" ???? ???? ? ????.
??? ??:
- ??? ?? : ???? ???? ???? ?? ???? ? ?? ???? ??? ? ????.
- ??? : ? ???? ????? ????? ?? ???? ??? ?? ???? ???? ?? ??? ? ????.
??? ???:
- ??? : ???? ?? ???? ?? ???? ??? ???? ???? ?? ???? ? ????.
- ?? ?? ?? : ?? ?????? ??? ?? ?? ??? ?????? ?????? ? ??? ? ????.
2.2.2 ??????? ??
??????? ????? ?? ???????? ???? ??? ?????. ???????? ??? ??? ???? ??? ?? ??? ?????. ?? ??? ??? ????.
- ?? ??? ?? : ???????? ? ???? ????? ??? ????. ?? ?? ???????? ?? ?? ???? ??? ????? ??? ? ????. ???? ???? ???? ???? ???? ?? ?????.
- ?? ?? : ? ???? ???????? ??? ?? ?? ??? ???? ??? ??? ??? ????? ???.
- ?? ?? : ???????? ??? ??? ?? ?? ??? ???? ??? ?????. ?? ??, ???? ????? ???? ???????? ?? ???? ?? ??? ????? ??? ? ????.
???????? ??:
- ?? ??? ?? : ?? ???????? ???? ?? ??? ? ?? ????, ??, ???? ? ????.
- ??? ?? : ???????? ??? ????? ?? ???? ?? ???? ??? ? ??? ????.
???????? ??:
- ?? ?? ?? : ???????? ????? ?? ???? ??? ?? ???? ?? ?? ??? ? ? ????.
- ???????? ?? ??? ?? : ???? ???????? ???? ??? ?? ???? ???? ??? ? ????.
3. ??? ??????? ?? ?? ??: ??? ???
????? ????? ???? Saga ??? ???? ??? ?????.
?? ?? ?????? ? ???? ?? ??? ?????. Coffee Service? ??? ???? ?? ?? ???? ???? ? ???? ??? ??? ???.
? ???? ?? ??? ??? ????.
- ?? ?? : ??? ?? ???? ?? ?????.
- ?? ???? ???? ????? : ?? ???? ??? ?? ???? ?????.
- Order Service? ??? ????? : Order Service? ??? ??? ???? ?????.
- ?? ???? ??? ????? : ?? ???? ??? ? ??? ???? ?? ??? ?????.
- ?? ???? ??? ????? : ?? ???? ??? ?????.
- ?? ????? ?? ?? ???? : ??? ???? ?? ????? ?? ??? '??'? ???????.
3.1 ?? ??
?? ??? Saga?? ? SagaItemBuilder? ?? ???? ??? ? ??? ?????. ActionBuilder? ??? ??? ?? ??? ?? ??? ?? ??? ???? ??? ??? ?????. ActionBuilder? ? ?? ??? ?????.
comComponent : ??? ???? ???? Bean ???????.
method : ??? ???? ?????.
args : ???? ??? ?????.
ActionBuilder
public class ActionBuilder { private Object component; private String method; private Object[] args; public static ActionBuilder builder() { return new ActionBuilder(); } public ActionBuilder component(Object component) { this.component = component; return this; } public ActionBuilder method(String method) { this.method = method; return this; } public ActionBuilder args(Object... args) { this.args = args; return this; } public Object getComponent() { return component; } public String getMethod() { return method; } public Object[] getArgs() { return args; } }
SagaItemBuilder
import java.util.HashMap; import java.util.Map; import java.util.Objects; public class SagaItemBuilder { private ActionBuilder action; private Map<Class<? extends Exception>, ActionBuilder> onBehaviour; public static SagaItemBuilder builder() { return new SagaItemBuilder(); } public SagaItemBuilder action(ActionBuilder action) { this.action = action; return this; } public SagaItemBuilder onBehaviour(Class<? extends Exception> exception, ActionBuilder action) { if (Objects.isNull(onBehaviour)) onBehaviour = new HashMap<>(); onBehaviour.put(exception, action); return this; } public ActionBuilder getAction() { return action; } public Map<Class<? extends Exception>, ActionBuilder> getBehaviour() { return onBehaviour; } }
????
import java.util.ArrayList; import java.util.List; public class Scenarios { List<SagaItemBuilder> scenarios; public static Scenarios builder() { return new Scenarios(); } public Scenarios scenario(SagaItemBuilder sagaItemBuilder) { if (scenarios == null) scenarios = new ArrayList<>(); scenarios.add(sagaItemBuilder); return this; } public List<SagaItemBuilder> getScenario() { return scenarios; } }
??? ?? ????? ???? ?????.
package com.example.demo.saga; import com.example.demo.saga.exception.CanNotRollbackException; import com.example.demo.saga.exception.RollBackException; import com.example.demo.saga.pojo.ActionBuilder; import com.example.demo.saga.pojo.SagaItemBuilder; import com.example.demo.saga.pojo.Scenarios; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; @Component public class DTC { public boolean commit(Scenarios scenarios) throws Exception { validate(scenarios); for (int i = 0; i < scenarios.getScenario().size(); i++) { SagaItemBuilder scenario = scenarios.getScenario().get(i); ActionBuilder action = scenario.getAction(); Object bean = action.getComponent(); String method = action.getMethod(); Object[] args = action.getArgs(); try { invoke(bean, method, args); } catch (Exception e) { rollback(scenarios, i, e); return false; } } return true; } private void rollback(Scenarios scenarios, Integer failStep, Exception currentStepFailException) { for (int i = failStep; i >= 0; i--) { SagaItemBuilder scenario = scenarios.getScenario().get(i); Map<Class<? extends Exception>, ActionBuilder> behaviours = scenario.getBehaviour(); Set<Class<? extends Exception>> exceptions = behaviours.keySet(); ActionBuilder actionWhenException = null; if (failStep == i) { for(Class<? extends Exception> exception: exceptions) { if (exception.isInstance(currentStepFailException)) { actionWhenException = behaviours.get(exception); } } if (actionWhenException == null) actionWhenException = behaviours.get(RollBackException.class); } else { actionWhenException = behaviours.get(RollBackException.class); } Object bean = actionWhenException.getComponent(); String method = actionWhenException.getMethod(); Object[] args = actionWhenException.getArgs(); try { invoke(bean, method, args); } catch (Exception e) { throw new CanNotRollbackException("Error in %s belong to %s. Can not rollback transaction".formatted(method, bean.getClass())); } } } private void validate(Scenarios scenarios) throws Exception { for (int i = 0; i < scenarios.getScenario().size(); i++) { SagaItemBuilder scenario = scenarios.getScenario().get(i); ActionBuilder action = scenario.getAction(); if (action.getComponent() == null) throw new Exception("Missing bean in scenario"); if (action.getMethod() == null) throw new Exception("Missing method in scenario"); Map<Class<? extends Exception>, ActionBuilder> behaviours = scenario.getBehaviour(); Set<Class<? extends Exception>> exceptions = behaviours.keySet(); if (exceptions.contains(null)) throw new Exception("Exception can not be null in scenario has method %s, bean %s " .formatted(action.getMethod(), action.getComponent().getClass())); if (!exceptions.contains(RollBackException.class)) throw new Exception("Missing default RollBackException in scenario has method %s, bean %s " .formatted(action.getMethod(), action.getComponent().getClass())); } } public String invoke(Object bean, String methodName, Object... args) throws Exception { try { Class<?>[] paramTypes = new Class[args.length]; for (int i = 0; i < args.length; i++) { paramTypes[i] = parameterType(args[i]); } Method method = bean.getClass().getDeclaredMethod(methodName, paramTypes); Object result = method.invoke(bean, args); return result != null ? result.toString() : null; } catch (Exception e) { throw e; } } private static Class<?> parameterType (Object o) { if (o instanceof Integer) { return int.class; } else if (o instanceof Boolean) { return boolean.class; } else if (o instanceof Double) { return double.class; } else if (o instanceof Float) { return float.class; } else if (o instanceof Long) { return long.class; } else if (o instanceof Short) { return short.class; } else if (o instanceof Byte) { return byte.class; } else if (o instanceof Character) { return char.class; } else { return o.getClass(); } } }
3.2 ????
?? ???? ???? ???? 3? ????: BillingService , OrderService , PaymentService.
?????
package com.example.demo.service; import org.springframework.stereotype.Service; @Service public class OrderService { public String prepareOrder(String name, int number) { System.out.println("Prepare order for %s with order id %d ".formatted(name, number)); return "Prepare order for %s with order id %d ".formatted(name, number); } public void Rollback_prepareOrder_NullPointException() { System.out.println("Rollback prepareOrder because NullPointException"); } public void Rollback_prepareOrder_RollBackException() { System.out.println("Rollback prepareOrder because RollBackException"); } }
?????
package com.example.demo.service; import org.springframework.stereotype.Service; @Service public class BillingService { public String prepareBilling(String name, int number) { System.out.println("Prepare billing for %s with order id %d ".formatted(name, number)); return "Prepare billing for %s with order id %d ".formatted(name, number); } public String createBilling(String name, int number) { System.out.println("Create billing for %s with order id %d ".formatted(name, number)); return "Create billing for %s with order id %d ".formatted(name, number); } public void Rollback_prepareBilling_NullPointException() { System.out.println("Rollback prepareBilling because NullPointException"); } public void Rollback_prepareBilling_ArrayIndexOutOfBoundsException() { System.out.println("Rollback prepareBilling because ArrayIndexOutOfBoundsException"); } public void Rollback_prepareBilling_RollBackException() { System.out.println("Rollback prepareBilling because RollBackException"); } public void Rollback_createBilling_NullPointException() { System.out.println("Rollback createBilling because NullPointException"); } public void Rollback_createBilling_ArrayIndexOutOfBoundsException() { System.out.println("Rollback createBilling because ArrayIndexOutOfBoundsException"); } public void Rollback_createBilling_RollBackException() { System.out.println("Rollback createBilling because RollBackException"); } }
?????
package com.example.demo.service; import org.springframework.stereotype.Service; @Service public class PaymentService { public String createPayment() { System.out.println("Create payment"); return "Create payment"; } public void Rollback_createPayment_NullPointException() { System.out.println("Rollback createPayment because NullPointException"); } public void Rollback_createPayment_RollBackException() { System.out.println("Rollback createPayment because RollBackException"); } }
??? ???????? ??? ?? ?????, ????? ??? ? ?????.
package com.example.demo.service; import com.example.demo.saga.DTC; import com.example.demo.saga.exception.RollBackException; import com.example.demo.saga.pojo.ActionBuilder; import com.example.demo.saga.pojo.SagaItemBuilder; import com.example.demo.saga.pojo.Scenarios; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class CoffeeService { @Autowired private OrderService orderService; @Autowired private BillingService billingService; @Autowired private PaymentService paymentService; @Autowired private DTC dtc; public String test() throws Exception { Scenarios scenarios = Scenarios.builder() .scenario( SagaItemBuilder.builder() .action(ActionBuilder.builder().component(orderService).method("prepareOrder").args("tuanh.net", 123)) .onBehaviour(NullPointerException.class, ActionBuilder.builder().component(orderService).method("Rollback_prepareOrder_NullPointException").args()) .onBehaviour(RollBackException.class, ActionBuilder.builder().component(orderService).method("Rollback_prepareOrder_RollBackException").args()) ).scenario( SagaItemBuilder.builder() .action(ActionBuilder.builder().component(billingService).method("prepareBilling").args("tuanh.net", 123)) .onBehaviour(NullPointerException.class, ActionBuilder.builder().component(billingService).method("Rollback_prepareBilling_NullPointException").args()) .onBehaviour(RollBackException.class, ActionBuilder.builder().component(billingService).method("Rollback_prepareBilling_RollBackException").args()) ).scenario( SagaItemBuilder.builder() .action(ActionBuilder.builder().component(billingService).method("createBilling").args("tuanh.net", 123)) .onBehaviour(NullPointerException.class, ActionBuilder.builder().component(billingService).method("Rollback_createBilling_ArrayIndexOutOfBoundsException").args()) .onBehaviour(RollBackException.class, ActionBuilder.builder().component(billingService).method("Rollback_createBilling_RollBackException").args()) ).scenario( SagaItemBuilder.builder() .action(ActionBuilder.builder().component(paymentService).method("createPayment").args()) .onBehaviour(NullPointerException.class, ActionBuilder.builder().component(paymentService).method("Rollback_createPayment_NullPointException").args()) .onBehaviour(RollBackException.class, ActionBuilder.builder().component(paymentService).method("Rollback_createPayment_RollBackException").args()) ); dtc.commit(scenarios); return "ok"; } }
3.3 ??
?? ?? ? ??? ??? ??
public String createBilling(String name, int number) { throw new NullPointerException(); }
??
2024-08-24T14:21:45.445+07:00 INFO 19736 --- [demo] [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' 2024-08-24T14:21:45.450+07:00 INFO 19736 --- [demo] [main] com.example.demo.DemoApplication : Started DemoApplication in 1.052 seconds (process running for 1.498) 2024-08-24T14:21:47.756+07:00 INFO 19736 --- [demo] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2024-08-24T14:21:47.756+07:00 INFO 19736 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2024-08-24T14:21:47.757+07:00 INFO 19736 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms Prepare order for tuanh.net with order id 123 Prepare billing for tuanh.net with order id 123 Rollback createBilling because RollBackException Rollback prepareBilling because RollBackException Rollback prepareOrder because RollBackException
? GitHub ???? ?????
4. ??
?????, Saga ??? ?? ????? ? ?? ?? ??? ??? ??? ???? ?? ??? ???? ?????. ??? ??????? ??? ??? ???? ?? ?? ??? ????? ?? ?????. ??? ??? ??? ???? ???? ??, ???????? ?? ??? ??? ?? ?? ????? ?????. Saga ???? ???? ???? ???? ?? ??????? ?????? ???, ??? ? ???? ?? ? ????.
??? ??? ???? Saga ??? ???? ? ?? ?? ??? ??? ?? ??? ???? ??? ?????!
?? ? ?? ??? ??: ?? ??? ?? ???? ??? ???? ??: ?? ? ?? ??
? ??? Saga ??? ?? ???? ??? ???? ??: ?? ? ?? ??? ?? ?????. ??? ??? PHP ??? ????? ?? ?? ??? ?????!

? AI ??

Undress AI Tool
??? ???? ??

Undresser.AI Undress
???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover
???? ?? ???? ??? AI ?????.

Clothoff.io
AI ? ???

Video Face Swap
??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

?? ??

??? ??

???++7.3.1
???? ?? ?? ?? ???

SublimeText3 ??? ??
??? ??, ???? ?? ????.

???? 13.0.1 ???
??? PHP ?? ?? ??

???? CS6
??? ? ?? ??

SublimeText3 Mac ??
? ??? ?? ?? ?????(SublimeText3)

Java? ??? ?? ??, ?? ? ??? (? : Projectreactor) ? Java19? ?? ???? ??? ??? ?????? ?????. 1. CompletableFuture? ?? ??? ?? ?? ??? ? ?? ??? ????? ?? ??????? ? ?? ??? ?????. 2. Projectreactor? ?? ? ??? ??? ???? ?? ???? ? ??? ???? ?? ? ?????? ?????. 3. ?? ???? ??? ??? ??? I/O ??? ? ??? ???? ?? ??? ????? ??? ???? ????. ? ???? ?? ??? ????? ??? ??? ??? ?? ??? ??? ?????? ???? ???? ?? ?? ??? ??????.

Java?? ??? ?? ?? ??? ???? ? ?????. ?? ???? ??? ?????. 1. ?? ?? ? ???? ??????? ?? ?? ?? ??? ???? ??? ?????. 2. ?? ??, ???, ??? ?? ?? ?? ???? ????? ?? ??? ??? ??? ?????. 3. ENUMMAP ? ENUMSET? ???? ?? ? ?? ???? ???? ??? ???? ? ?????? ?????. 4. ?? ?, ??? ?? ?? ??? ?? ????? ?? ??? ??? ?????.? ????? ?? ???? ????????. ??? ???? ???? ?? ??? ????? ??? ?? ? ??? ?? ?????? ???????.

Javanio? Java 1.4? ?? ? ??? IOAPI???. 1) ?? ? ??? ?????, 2) ??, ?? ? ??? ?? ?? ??, 3) ? ??? ??? ???? 4) ?? ??? ?? IO?? ? ????? ?????. 1) ? ?? IO? ??? ?? ??? ???, 2) ??? ??? ?? ???? ?????, 3) ???? ?????? ???? 4) ??? ?? ??? ?? ?? ? ??? ?????. 1) ??? ??/??? ??? ?? ?????, 2) ???? ???? ???? ?? ???? ???????. 3) ??? ??? ??? ???????.

Java? ????? ????? ??? ??? ?? ???? ?? ?? ??????, ?? ? ???? ? ??? ????. ?? ???? ??? ??? ???? ??? ??? ???? ?? ??? ??? ????. ???? ???? ??? ??, ?? ??? ???? ???? ?? ??? ?? ???? ?? ?????. ???? ?? ?? ??? ?? ?? ??? ?????. ?????? ?? ??? ??? ???? ?? ??? ??? ?? ??? ???? ???? ??? ?? ??? ?????? ???? ????? ??? ?? ?? ???, ?? ? ?? ???? ??? ??? ?????. ???? urlclassl? ?? ??? ??? ??? ?? ? ? ????

?? ?? Java? ?? ???? ?? ? ? ? ????? ????, ? ??? ??? ??? ??? ???? ? ????. 1. ?? ?? hashcode () ???? ???? ?? ?? ???? ?? ??? ?? ?? ???? ?????. 2. ?? ??? ??? ?? ?? ???? ??? ??? ? ????. ?? ??? ?? ? ??? ??? ?????. JDK8 ? ?? ? ??? ?? ?? (?? ?? 8) ??? ????? ?? ???? ?? ? ??? ?????. 3. ??? ?? ???? ?? ???? ?? equals () ? hashcode () ???? ?? ???????. 4. ?? ?? ??? ???? ?????. ?? ?? ??? ???? ?? ?? (?? 0.75)? ??? ?? ? ???; 5. ?? ?? ??? ??? ??? Multithreaded?? Concu? ???????.

Java ??? ??? ???? ??? ??? ??? ?????, ???? ????, ?????? ??? ? ????. 1. ??? ????? ???? ??? ? ? ??? ?? ?? ????? ???? ? ???? ??????. 2. ???? ?? ?? ???? ??? ??? ???? ?? ?? ???? ??? ??? ? ????. 3. ???? ???? ??? ??? ?? ??? ?? ? ? ??????. 4. ?? ?? ?? ??? ? ??? ??? ?? ????? ?? ?? ??? ??? ? ????. 5. ??, ?? ?? ??, ?? ?? ?? ???, ????? ?? ?? ? ???? ??? ????? ??????.

Java? ??? ???? ??? ??? ??? ???? ???? ??? ?? ?? ????. ?? ??? ?? ?? ?? ??? ???? ???? ??? ??? CheckedException? ?? ??? ??????. ??? ??? ?? ???????. ??, ?? ??? ??? ???? ??? ???? ??? ?? ? ??, ?? ?? ?????????. ??, ??? ??? ???? ???? ??????, ????? ??? ???????. ??, ??? ?? ??, runtimeexception ?? ??? ?? ?? ?? ???? ?? ???? ??? ???????.

Java? Singleton Design Pattern? ???? ??? ???? ? ?? ?? ??? ? ?? ??? ?? ??? ??? ???? ???? ?? ???? ?? ???? ???? ??? ?????. ?? ???? ??? ?????. 1. ?????, ? ????? ? ?? ??? ?? ? ?? ????, ?? ?? ??? ?? ??? ???? ?? ??? ?????. 2. ???-?? ??, ??? ?? ?? ?? ?? ??? ?? ?? ??? ???? ??? ???? ? ???? ?? ??? ????. 3. ??? ?? ?? ????? ?? ????? ??? ??? ?? ??? ? ??? ??? ?? ?? ????? ?????. 4. ?? ??? ???? ???, ??? ??? ? ?? ??? ???? ?? ??? ???? ??? ??? ?????. ?? ??? ?? ?? ?? ??? ??? ? ????.
