книги хакеры / журнал хакер / 171_Optimized
.pdf
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
C |
|
E |
|
|||
|
|
X |
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
||
|
F |
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
r |
|
P |
|
|
|
|
|
NOW! |
o |
||
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|||
|
|
|
|
to |
110 m |
||||
w Click |
|
||||||||
|
|
||||||||
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
. |
|
|
|
|
|
.c |
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
df |
|
|
n |
e |
||
|
|
|
|
-xcha |
|
|
|
Кодинг
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
ХАКЕР 04 /171/ 2013 |
|
|
|
|
|
|
||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x cha |
|
|
|
|
сообщения JMS, в процессе которой выполняет операции с базой данных и отправляет в ответ подтверждение. От заказчика появилось требование вести в базе данных журнал обработки сообщений, в который необходимо записывать информацию о результатах обработки. Для этого был реализован сервис LogService с методом log(String message, Throwable cause).
Измените приведенный код, добавив запись в журнал любых результатов обработки и обеспечив корректную обработку ошибок:
@Transactional
public void processDocument(Document
document) throws ServiceException,
MessagingException {
if (isValid(document)) {
documentService.store(document);
messagingService.send
(Acknowledgements.documentReceived
(documentt));
} else {
messagingService.send
(Acknowledgements.documentInvalid
(document));
}
}
Расскажите, как можно протестировать полученный код. Расскажите, как должен быть реализован метод audit, чтобы гарантировать запись в журнал любых результатов.
РЕШЕНИЕ
Для начала необходимо разобраться, что делает приведенный код: мы видим здесь распределенную транзакцию, в которой проверяется корректность входящего документа, его сохранение в базу данных и отправка подтверждения. Судя по сигнатуре метода, какие-то из этих операций могут сгенерировать исключение ServiceException, а отправка подтверждения, скорее всего, генерирует еще и MessagingException. Нельзя исключать, что в процессе обработки может также возникнуть RuntimeException. Мы не знаем, с какой версией Java работает этот код,
ŖşŨŞŮţŖŵ ŠŤŢťŖţŞŵ! ŮšŞ ţŖŢŠŖŭśŧŨŘśţţűś ŝŖŚŖŭŠŞ, ŞŢű ŞūŤťũŗšŞŠũśŢ! ŗśŧťšŖŨţŤ, ŗśŝ ŦśřŞŧŨŦŖŬŞŞ, ŗśŝSMS, ţŖ ŢŖŠŧŞŢŖšŲţŤş ŧŠŤŦŤŧŨŞ. ŞťŦŤ ŗśŧťšŖŨţűś ŖşŪŤţűŧŖŢűŢ řŦŖŢŤŨţűŢ ŭŞŨŖŨśšŵŢťŦŤŧŲŗŖ ţśŝŖŗűŘŖŨŲ.
ЗАДАЧИ ОТКОМПАНИИ
ABBYY
Решение этих задач ждет тебя на нашем диске. Должно же быть что-то, что могло бы подвигнуть тебя вставить его в дисковод!
Предполагается, что авторизованный на сайте пользователь получает специального вида cookie, которую нам и нужно украсть
<имя пользователя>
<Текст комментария>
<аватар>
Ответить
Редактировать
Удалить
Рис. 1
поэтому для краткости изложения будем считать, что это Java 7. Попробуем его модифицировать:
public interface DocumentProcessor {
Result processDocument(Document document) throws
ProcessingException;
}
public class DefaultDocumentProcessor implements
DocumentProcessor {
@Transactional
public Result processDocument(Document document) throws
ProcessingException {
try {
if (isValid(document)) {
documentService.store(document);
messagingService.send(Acknowledgements.
documentReceived(document));
return DOCUMENT_PROCESSED;
} else {
messagingService.send(Acknowledgements.
documentInvalid(document));
return DOCUMENT_INVALID;
}
}catch (ServiceException | MessagingException e) { throw new ProcessingException(e);
}
}
}
public class LoggingDocumentProcessor implements
DocumentProcessor {
@Inject
DefaultDocumentProcessor delegate;
@Inject
AuditService auditService;
public Result processDocument(Document document) throws
ProcessingException {
try {
Result result = delegate.processDocument(document);
auditService.audit("documentProcessed", result);
return result;
ŦśŮśţŞś ŧŨŖŦŤş ŝŖŚŖŭŞ ŤŨ ŭŞŨŖŨśšŵ:
ŘƁŶźžƂžƆ řŶƅƄƃŻƃƀƄ žŽ ŧŶƃƀƈ-ťŻƈŻƆŷƉƆŹŶ(gvb81@list.ru)
В декабрьском журнале «Хакер» за 2012 год на странице 101 была опубликована задача № 3 про лягушат. Решать ее предложили с помощью кругов Эйлера — не знаю, как другие читатели журнала, но я в такой способ решения так и не въехал. Поэтому решил все-таки поломать себе мозг долгими логическими выкладками, и у меня, как ни странно, получилось более быстрое и простое решение.
Исходя из условий задачи, лягушата могут быть: зеленые (З) или пестренькие (П), грустные (Г) или веселые (В), сидящие на берегу (Б) или плавающие в воде (W). Получается не так уж и много возможных комбинаций: ЗГБ, ЗГW, ЗВБ, ЗВW, ПГБ, ПГW, ПВБ, ПВW. Уточняем: если лягушонок зеленый, то он веселый — значит, вычеркиваем комбинации ЗГБ и ЗГW. Если лягушонок грустный, то он сидит на берегу — вычеркиваем ПГW. Если лягушонок пестренький, то он плавает в воде — вычеркиваем ПГБ и ПВБ.
В итоге остается только три возможных комбинации: ЗВБ, ЗВW и ПВW. Теперь сверяем их с утверждениями. Первое утверждение неверно, поскольку возможна комбинация ЗБВ. Второе утверждение неверно, потому что возможна та же комбинация ЗБВ. Третье утверждение верно, поскольку подтверждается всеми тремя возможными комбинациями. Четвертое утверждение неверно, поскольку возможна комбинация ПВW. Пятое утверждение неверно, поскольку опровергается всеми тремя возможными комбинациями. И наконец, шестое утверждение неверно, потому что возможна та же комбинация ЗВБ.
Думаю, что мой логический способ решения задачи будет более понятен людям с математическим складом ума, чем круги Эйлера, и особенно подойдет в тех случаях, когда не нужно разбираться с десятком и более возможных комбинаций.
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
ХАКЕР m |
04 /171/ 2013 |
|||||||
|
|
|||||||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|
Задачи на собеседованиях
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
||
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
|
to |
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
m |
||
111Click |
|
|
|
|
|
||||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x cha |
|
|
|
|
}catch (ProcessingException | RuntimeException e) { auditService.audit("documentProcessingFailed", e);
throw e;
}
}
}
Как можно увидеть в получившемся фрагменте кода, мы выделили интерфейс обработки документов и добавили еще одну его реализацию, осуществляющую запись в журнал.
Это было необходимо, поскольку у нас используется декларативная разметка транзакций (причем, скорее всего, на стеке технологий Spring, а не JEE, иначе была бы использована аннотация TransactionAttr ibute), соответственно, вероятны ошибки, возникающие за пределами метода processDocument, например в фазе commit. В новой реализации мы корректно обработаем такие ошибки и сделаем запись в журнал
«documentProcessingFailed».
Этот код будет работать исходя из предположения, что ошибки записи в журнал аудита являются фатальными для системы, — именно поэтому исключения, возникающие в методе audit, не обрабатываются.
Кроме того, новый код использует перегруженную версию метода audit со следующей сигнатурой:
public void audit(String messageKey, Object… params);
Такой интерфейс позволяет делегировать формирование сообщения из прикладного кода метода processDocument в сервис аудита, в котором сообщение может быть построено, например, с помощью класса MessageFormat из стандартной библиотеки по заданному ключу в файле ресурсов приложения.
После реализации журнала работы мы получаем три возможных сценария работы кода, на которые, соответственно, должно быть написано три приемочных теста.
Код будет работать исходя из предположения, что ошибки записи в журнал аудита фатальны для системы, — именно поэтому исключения, возникающие в методе audit, не обрабатываются
1.Тест на обработку корректного документа. Проверяет, что документ сохраняется в БД, отсылается подтверждение и появляется соответствующая запись в журнале работы.
2.Тест на обработку заведомо некорректного документа, например с переопределенным методом isValid. Проверяет, что результатом обработки такого документа является отосланное подтверждение documentInvalid и запись в журнале.
3.Тест на обработку ошибок, например с перегруженным методом documentService.store, генерирующим исключение ServiceException.
Проверяет, что в такой ситуации единственным результатом работы является запись в журнале.
Поскольку журнал работы сохраняется в базе данных, метод audit должен выполняться в отдельной транзакции — иначе результаты его работы могут не сохраниться из-за отката основной бизнес-транзакции, если метод audit вызывался внутри нее.
ЗАДАЧАОТКОМПАНИИSOFTLINE№1
Что выведет данный скрипт? Объясните почему.
<?php
function fn(&$var)
{
$var = $var - ($var/10 * 5);
return $var;
}
echo fn(100);
?>
РЕШЕНИЕ
Перед тем как начать пересчитывать предполагаемый результат функции для параметра 100, проверим корректность реализации и вызова.
ŭŞŨŖŨśšŲ! ťŦŞŧűšŖş ţŖŢŧŘŤŞ ŦśŮśţŞŵ, ŞŢű ŞūŤťũŗšŞŠũśŢ! ŦũŠŤťŞŧŞ ŘŤŝŘŦŖůŖŴŨŧŵ
ŘťŤŢŵŨŤŢ
ŞŞŧťŤŦŭśţţŤŢ ŘŞŚś, ťŤųŨŤŢũ
šũŭŮśťŤšŲŝũşŧŵ ųšśŠŨŦŤţţŤş ťŤŭŨŤş.
Обращаем внимание, что аргумент функции принимается по ссылке (&$var), соответственно, корректно в нее можно передать только переменную. В нашем же случае в функцию передается константа, поэтому ожидаемый результат работы скрипта — сообщение об ошибке:
PHP Fatal error: Only variables can be
passed by reference
ЗАДАЧАОТКОМПАНИИSOFTLINE№2
Как можно сделать анимированную иконку средствами только CSS с анимацией части изображения, без использования растрового фона?
РЕШЕНИЕ
Используется базовый класс с описанием параметров основного блока — каркаса кружки, два класса с модификаторами :after и :before для создания уровня жидкости и ручки, а также класс :hover для отображения состояния при наведении курсора. В базовом классе указаны параметры анимации — анимируемое свойство, скорость анимации и тип анимации:
.mug_animate {
-webkit-box-shadow: inset 0 -3em 0 0
#2C2C2C;
box-shadow: inset 0 -3em 0 0
#2C2C2C;
margin: 0 auto;
margin-bottom: 1em;
height: 2.5em;
margin-top: 1.25em;
position: relative;
width: 1.5em;
-webkit-transition: all 1000ms
linear;
-moz-transition: all 1000ms linear;
-o-transition: all 1000ms linear;
-ms-transition: all 1000ms linear;
transition: all 1000ms linear;
}
.mug_animate:after {
border: .25em solid #2C2C2C;
border-right: none;
border-radius: .75em 0 0 .75em;
content: '';
height: 1.5em;
left: -1em;
position: absolute;
top: .25em;
width: .75em;
}
.mug_animate:before { border-radius: 0 0 0.2em 0.2em;
top: -0.5em;
left: -0.25em;
position: absolute;
border: 0.25em solid #2C2C2C;
height: 2.5em;
width: 1.5em;
content: "";
}
.mug_animate:hover {
-webkit-box-shadow: inset 0 0em 0
0 #2C2C2C;
box-shadow: inset 0 0em 0 0 #2C2C2C;
}
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
|
|
|
.c |
|
||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-xcha |
|
|
|
|