×

Code review for Beginners/Juniors

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

Я не знайшов відповідної теми, тому ризикнув створити нову.

Якщо вигорить, то пропоную дотримуватися наступного формату прохання рев’ю коду:

1. Опис проєкту (що робить).
2. Посилання на репо (куди ж без нього).
3. #technology #language

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному2
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

1. Всім привіт! Потрібна ваша допомога. Я нещодавно створив свій перший фротненд-проект — сайт про Київський торт, який містить текстову інформацію про нього, картинки, а також форму підрахунку, яка дозволяє вирахувати, скільки фізичних вправ треба зробити, щоб відновити фігуру після певної кількості шматочків цього торта. Але якщо текст, картинки і стилізація відображаються нормально, то от ця форма для підрахунку даних і виведення результатів не працює — при введенні усіх необхідних даних і натисканні кнопки «Підрахувати» форма або перезавантажує сторінку, або ж видає помилку «404 Not Found». В ідеалі форма має видавати результат у вигляді загальної енергетичної цінності і кількості фізичних вправ, які необхідно зробити. Я не спеціаліст в ІТ, тому знайти помилку не зміг, але сподіваюсь що ви зможете знайти помилку в коді і виправити її, щоб проблема більше не виникала.
2. codepen.io/...​-the-styleful/pen/zYeRmjP
3. HTML, CSS і JavaScript

Коментар порушує правила спільноти і видалений модераторами.

Зацените мои проекты Python/Django, плиз

github.com/...​PortfolioPositionsReports — Python script that loads a list of stocks or ETF tickers from Google Spreadsheet, then for each position generates a report with charts and sends it to the email. You can effortlessly change the set of items in the watchlist using your smartphone, as long as it works with Google Spreadsheets.

github.com/...​ust/django-advanced-forms — This project aims to demonstrate the creation and processing of the large and complex form in Django using django-crispy-forms.

1. Давно практикую осознанные сны, поэтому написала программу-будильник для ОС. Работает. Главная суть в том, что она периодически подбуживает спящего слегка слышимой сквозь сон вибрацией звука варгана, с заданным пользователем интервалом времени и этим напоминает спящему, что нужно начать практику и выполнить план в осознанном сне. Подробное описание функционала на github. Я совсем недавно закончила курсы по Python и хотелось бы найти человека, который смог бы причесать мои навыки. Поэтому если глядя на мой код, вы можете дать совет, как сделать что-либо проще или лучше, то буду очень благодарна :)
2. github.com/...​/Clock-for-lucid-dreaming
3. Python

Честно, говоря, до этого лет 15 успешно практикую осы вообще без внешних вспомогательных устройств и понимаю, что способность осознаваться во сне это — натренированный умственный навык. Начинающим ОСерам такая программка может и нужна, но на самом деле это внешний костыль, все держится на привычке полагаться только на свою башку. И перед сном нужно мысленно между бровями крепко закрутить в свое подсознание шуруп намерения осознаться для выполнения конкретного плана действий. Ну или мысленно прибить гвоздями к своему внутреннему черному экрану белую табличку с планом действий, а потом спокойно уснуть. И под утро обычно, когда мозг уже отдохнул, робот твоего подсознания отправится читать и выполнять план на висящей у него табличке.... Кстати, математика и программирование оттачивают дисциплину мышления и осознанность каждом шаге, необходимую для того чтобы осознаться во сне. Ничего лучшего для тренировки осознанности во сне я не знаю, почему, собственно, я этим и занимаюсь.

Я запрограммировал ассоциативное мышление

github.com/oleg-dorozhko/dvig_1_11 <---- Это исходники GNU

y95444k9.beget.tech <--- Это сайт — простая демонстрация

Спрятал код ибо нечего еще показывать. Не всем psr соответствует еще.

Коментар порушує правила спільноти і видалений модераторами.

Привет всем! В свободное от работы время делаю opensource проект на Vue.js (с использованием Vuex) и PIXI.js. Нужны советы по архитектуре, по той части приложения которая написана на Vue.js. Если есть возможность помочь советом — пишите в ЛС или linkedin 27198416b, буду весьма благодарен!

Анализ качества кода PHP сайта на CodeIgniter youtu.be/EVj7ER4sf-I

1. Сайт с билетами на самолет
2. github.com/aqwrel/tickets.vue
3. JS, Vue, html, css
Был бы очень благодарен если подскажете по багу с валютой. Как это исправить?
Спасибо

Якось підозріло, в профілі вказано місто Дніпро, а ціна на квитки в проекті в рублях 🤔

1 Простой блог на django с базовым функционалом
github.com/SkyFoxq/django-blog-site skyfoxq.pythonanywhere.com
3 #python #django

Всем Привет! Пожалуйста помогите начинающему, подскажите какой алгоритм создания формы отправки данных в Laravel? Только начал изучать, знаю, что необходимы роуты, контроллер, вьюха, где будет прописана форма отправки...также надо создать БД, провести миграцию, редактировать файл миграции,для взаимодействия с бд создаётся модель...вот на этом этапе беда, не могу создать форму и получать данные из
Видеурок может есть или кто что знает? Спасибо большое!!

1. Движок для игры в русские шашки. Генерация ходов с использованием магических битбордов, генерация и поддержка эндшпильных таблиц в своём формате (неоптимизирована по памяти, для генерации 6-фигурных таблиц требовалось примерно 128G оперативной памяти, семифигурные сгенерировались частично на 640G оперативной памяти), метод MCTS для выбора хода. Сыграть можно на mustitz.host.funtoo.org:2201, но боюсь что много трафика может не выдержать.
2. github.com/mustitz/checkers
3. Linux, C99

1. Генерация конечного автомата в виде магической таблицы для быстрого вычисления силы руки в разных вариантах покера. Или для быстрого вычисления любой дискретной функции. Прилагаются магические таблицы для омахи по семи картам (пять шагов board, потом 6*2 = 12 шагов для покет + max), Texas Hold`em по пяти и семи картам, Six Plus по пяти и семи картам.
2. github.com/mustitz/yoo-ofsm
3. Linux, C99

1. Цель игры — собрать золота за возможно меньшее количество ходов. В зависимости от того, где находится красный квадратик — гл.герой — доступны те или иные действия левой и правой кнопкой мыши.
2. giprozhorka.space/mix
3. quantum crypted javascript

Головоломка должна быть именно такой. Исследуйте ее и будете вознаграждены.

Добрий день. Прошу оцінити мій проект. Найбільше цікавить Bаша думка по архітектурі і правильності написання коду на фронті. Так як це перший проект на Vue, просьба пройтись максимально жорстко.
1. Сайт з фейковими ставками на футбол
2. github.com/someuser94n/fakebet
3. JS, Vue

Добрый день, ребята прошу сильно тапками не кидать. А помочь советом. Что и где можно причесать, чтобы было не стыдно вставить линк на гит в резюме. Сразу говорю, что в разрабы не мечу, а только в тестировщики)).
1. Приложение погоды
2. github.com/ktulxy/MyWeather?files=1
3. Java
Спасибо.

Всем доброго дня. Изучаю vuejs, параллельно пытаюсь трудоустраиваться. Уже по трем тестовым заданиям, получаю ответы вроде «Задание выполнено неудовлетворительно». Хотелось бы понять, что не так и на что обратить внимание в дальнейшем изучении. Вот последнее задание
1. Два задания в одном. Калькулятор простых дробей и удаление комментариев, при получении ответа от Websocket. Т.е. отправили идентификатор комментария и когда получили ответ от сервера — удалили
2. github.com/...​e-test-task-fraction-calc
3. JavaScript, vuejs

хорошый топик стартовали, но почему-то заглохло все. есть еще заинтересованные?

Всем привет, оцените(покритикуйте) пожалуйста мой код, я начинающий.
1. Слайдер-карусель(по типу фейсбука)
2. github.com/...​r-Carousel-no-jquery-.git
3. JavaScript

Кроме багтраппинга, есть ли еще какие проблемы?
1. STUN client
2. github.com/...​ntexample/STUNClient.java
3 .джава,андроид.STUN это протокол который позволяет узнавать свои координаты по ту сторону NAT. Обычно это нужно для p2p обмена данными через UDP транспорт, при отсутвии «статического айпи».

Коментар порушує правила спільноти і видалений модераторами.

-

Приветствую друзья, помогите пожалуйста расишифровать ответ., за одно постебать код, на правах цивилизованного разработчика (не постсовковогоОчколупоЗадрота).
Прошу разьяснить мне такой момент.
1. Тестовое задание, Регистрационная форма, регистрация, авторизация, профиль пользователя.
2. github.com/wwwork/js_bootstrap_php_test_form
3. php/jquery/bootstrap

Таблица:

CREATE TABLE IF NOT EXISTS `usr` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`firstname` varchar(120) NOT NULL,
`lastname` varchar(120) NOT NULL,
`username` varchar(120) NOT NULL,
`email` varchar(120) NOT NULL,
`pass` varchar(120) NOT NULL,
`ava` varchar(120) CHARACTER SET utf16 NOT NULL,
PRIMARY KEY (`id`),
KEY `firstname` (`firstname`,`lastname`,`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=85 ;

Получил такой ответ:
2) Отсутствует единый стиль оформления кода. Для отступов используются то табы, то пробелы. Открывающая фигурная скобка то перенесена на следующую строку, то нет. Сами отступы тоже имеют различную длину. Все это значительно ухудшает читаемость кода.
3) Отсутствует явно выраженная архитектура кода. Вся серверная логика обрабатывается 2-мя файлами (send.php + inc/class.php). Как поддерживать и расширять данное решение — не понятно.
4) JS часть задания явно хромает. eval() и копипаст — сразу бросается в глаза.
5) таблица пользователей не оптимизирована и не имеет всех необходимых индексов.
====
По таблице не могу понять, каких не хватает индексов? Если у меня запрос идёт только по мылу и паролю.
В send.php ипользюу методы из класса. Не более.

По таблице не могу понять, каких не хватает индексов? Если у меня запрос идёт только по мылу и паролю.
Ну вот навешенного на мыло индекса и не хватает. Причем мыло должно быть unique.

Мне интересно, что такого ваш

постсовковыйОчколупоЗадрот
написал в пункте (1) ответа, что вы постеснялись этот пункт выложить))

1.Консольный Блек Джек
2.http://goo.gl/7sgSHO
3. .Net, C#

Коментар порушує правила спільноти і видалений модераторами.

Всем привет, хочу показать мой небольшой проектик:
1. Если в консоли ввести «curl curls.top» приложение возвращает курс валют НБУ, Привата и средний по «рынку». Для этого естественно надо иметь консоль и curl, или HHTPie (http curls.top), или wget...
2. github.com/Molly101/curls.top
3. JavaScript, Nodejs, Redis

Що ж, спробуємо.
1. Тестове завдання на мідла в одному банку (проходив не я, я не мідл, до того ж, але для практики пробую такі штуки робити). Повний текст завданя в README
2. github.com/...ewsTestTask_AndroidMiddle
3. Android, Java (ні, не Котлін)

1. Проект для управления музыкой. Аналогов на рынке не встречал.
2. github.com/...CandyOgre/MusicPerfectizr
3. C#, WinForms, MetroFramework, taglib-sharp

Сюда запостю.
У вас в FileOperator.GetNewFilePath много файловых операций (Directory.CreateDirectory например...) и нету ни одного обработчика исключений, на мой взгляд всякие IOException нужно перехватывать и обрабатывать внутри этого метода.

Спасибо за отзыв! Постараюсь чтото с этим сделать

Проект конечно не большой, сильно не разгонишься.
— первое что бросилось в глаза — это название метода (еще и паблик) DoStuff(). Почти как Foo() :) Я думаю можно придумать какое-то более интеллектуальное название...
— не вижу обработки ошибок, получается если что-то упадет (кинет исключение) то приложение либо падает либо непонятно что делает. Вот метод DoStuff(), если File.Copy завалится, исключение проглотится — будет ли это считаться за корректную работу метода/логики?
— AltForm.cs & MainForm.cs, по сути логика программы находится прямо в обработчиках событий контролов прямо на форме. В личных мелких програмульках я конечно тоже так делаю, но если уж выставлять на показ — можно как-то и облагородить (mvp например).

Покритикуйте, будь-ласка, код. Гра BlackJack, використовувалася Java EE 7 (без фреймворків). При бажанні, легко запускається на Tomcat (в README описано, що потрібно зробити).
github.com/hasheniuk/blackjack

Посмотрел.

Steps по созданию схемы в PGSQL я-бы убрал в EntityManagerFactorySingleton.

Оцініть будь ласка код, pet project на джуна Java
1.Рейтинговий сервіс для підприємств в сфері послуг.
2. github.com/dimitrij94/KeyStyle
3. Java

Останній коміт в «new-place-page» brunch, я дещо переосмислив концепцію проекту тому багато чого буде змінено.

Доброго времени суток, посмотрите пожалуйста код.
1. Змейка
2. github.com/scagenek/Snake
3. Java
Буду рад Вашим замечаниям и дополнениям

Мое имхо (больше по стилистике, я думаю, что логика класса корректно написана):

class Board

1. [20-25] константы лучше обьявлять со модификатором static, на то они и константы, что могу существовать без сущности =).
2. [29, 34] int по умолчанию проинициализирован 0, в то время как у bool — false.
3. вместо loadImages, лучше сделать так (это та же константа получается):
private final static Image BALL = new ImageIcon("img/dot.png").getImage();
и потом вынести все картинки в ENUM и уже его использовать
4. TAdapter пелену из if можно как-то упростить, но хз как. нужно будет детально поиграться. Так же сам TAdapter лушче передавать через setter for class Board.

Генерация нового яблока хреновая. Она иногда может фейлить. Это недопустимо, может в редкий кошмар вылезти.
Магические константы есть. Неоднообразное форматирование и не везде отступы правильно соблюдаются.
По-моему несколько не чётко написано и может ещё что-то быть, не смотрел сильно.

Посмотрел. Несколько мыслей.
1) Для анимации змеи вовсе не нужно делать перерасчёт всех ее координат. По сути мы можем добавлять еще одну голову и отрубать кусок хвоста. Можно подключить Deque для этого.
2) По коду очень много лишних скобок. Это флуд и его желательно выкосить.
3) ИМХО есть избыточные взаимосвязные переменные типа
leftDirection = true;
downDirection = false;
их можно заменить на одну целочисленную типа verticalDirection в диапазоне значений {-1,0,1}

Смотрю, тут в основном Java просят о ревью.
Веб-деведоперы видимо или всё знают, или боятся :)

Добрый день! Пытаюсь изучить Java Spring, правда пока не очень получается. Пишу «Домашнюю бухгалтерию» (пишу громко сказано, т.к. я пока еще в самом начале):-) По специальности я не программист, разобраться трудновато, прошу посмотреть код, и подсказать как исправить ошибку (в чем ошибка я в принципе понимаю). Заранее спасибо!

github.com/FeschenkoNatalia

Добрый день! Извините за то, что долго, поверьте на то были объективные причины.
Что сделано: полностью переписала проект, ошибки не выдает, но еще много чего не доделано. Постаралась более-менее исправить то, что Вы написали. Сразу говорю, не все получилось, т.к. с github я тоже еще разбираюсь. Если будет время и желание, посмотрите (покритикуйте) пожалуйста. Заранее большое спасибо!
github.com/FeschenkoNatalia/Spring

1. В git необходимо помещать только исходный код, все бинарники (папки out и target) необходимо засунуть в .gitignore дабы исключить попадание их в репозиторий.
2. Если используете maven, то следуйте конвенциям и создайте типичную структуру папок для maven’a.
2. Сборка проекта: настройте сборку через maven в war файл. По желанию, можно подключить jetty plugin — он позволит вам запускать ваш проект в один клик.
3. Структура исходников: создайте отдельные пакеты для контроллеров, дао, сервисов.
4. Лучше всего, одно приложение — один репозиторий (если это не связанные модули). У вас намешано.

Как исправите — можно будет дальше продолжить :-)

Добрый день! Извините за то, что долго, поверьте на то были объективные причины.
Что сделано: полностью переписала проект, ошибки не выдает, но еще много чего не доделано. Постаралась более-менее исправить то, что Вы написали. Сразу говорю, не все получилось, т.к. с github я тоже еще разбираюсь. Если будет время и желание, посмотрите (покритикуйте) пожалуйста. Заранее большое спасибо!
github.com/FeschenkoNatalia/Spring

1. Первый пункт не выполнен, все так же нужен .gitignore на бинарники + добавить *.iml и .idea. Закоммить и удалить из репозитория лишнее.
2. По структуре — более менее.
3. Подредактируйте pom.xml: форматирование, уберите копирайты mkyong — в общем, подправьте под себя. Погуглите про каждую директиву, которая была использована для понимание что это такое.
4. Transaction.java: именование полей — только camelCase, никакого snake_case, поля сделайте закрытыми.

Бегло пробежался. Когда исправите это, то отпишите — будем смотреть дальше.

Добрый день! Постаралась исправить все Ваши замечания:
п.1. — исправила (добавила .gitignore, убрала лишние файлы и папки).
п.2 — не трогала, т.к. «более-менее»:-)
п. 3 — с pom.xml не все получилось, т.к. если его глобально править, можно сбить настройки и тогда проект maven-ом не собирается. Чуть подправила настройки, в выложенной редакции проект собирается и работает,по крайней мере до той стадии, до которой он написан:-)).
п. 4 — откорректировала.
Если можно, посмотрите пожалуйста.
Огромное Вам спасибо!:-)
P.S. Фактически на сейчас работают стандартные функции (просмотр списка транзакций, каждой отдельной транзакции, корректировка, добавление, удаление транзакции).
Еще хочу добавить возможность выборки транзакций по каждому из параметров за указанный период.

1. findById(Integer), delete(Integer) на уровне дао\сервисов — сменить на примитив. Поможет на этапе компиляции отловить NPE.
2. Тесты? Гуглите в сторону junit & mockito.
3. Почему-то зависимости TransactionServiceImpl не private, надо бы закрыть.
4. Наблюдается логика в контроллере — вынести в сервис (populateDefaultModel, sourceType — это ведь отдельный тип?).

Мысли.
1) Начиная с семерки и восьмерки можно использовать diamond operator в дженериках. Пример new HashMap<>().
2) Этот шаблон — очень сложен. Он совершенно не supportable
TRANSACTION_DATE_PATTERN = «^((0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](20)\\d\\d)$»;
в данном случае я-бы выбрал несколько отдельных проверок которые проверяют что есть правые слеши и год-месяц-день попадают в диапазон через кастинг в целое.

Здравствуйте,
Буду благодарен если у кого-нибудь из Вас найдётся время на ревью моего проекта.
Главный вопрос, который меня интересует — на сколько проект «нормальный» с точки зрения что это проект джуника? (чтоб я мог отправлять его вместе с резюмешкой).
Данный проект я писал с нуля по мере прохождения обучения. Его развитие проходило примерно в ключе db + jdbc + console ui -> hibernate -> spring + web ui. Итоговая цель — накопить(совместить) в проекте все технологии чтобы было видно их применение. Я идеале, я понимаю, что такое должно быть в разных проектах. Поэтому в нём внутри есть места, где есть «своеобразное дублирование» кода, например 2 конструктора: public Student(long person_id, long group_id) и public Student(Person person, Group group). Может быть ещё какие-то моменты. Более детальное описание есть в README.md
— Проект «Академия» (db/CRUD/search/console-ui/web-ui/)
— github.com/Igor-ua/Academy
— Отделил от общей массы Spring-ветку github.com/...ademy/tree/springboot_war удалил оттуда лишнее и развернул её на openshift’е. Доступна по адресу: academy-spring.ddns.net
— #Java #JDBC+MySQL #Hibernate+H2 #Logging #Spring/SpringBoot + H2(DATA JPA, MVC, Security) #WEB(HTML, CSS, JS, JQuery, Thymeleaf, Bootstrap)
Заранее благодарен за Ваши отзывы, если таковые будут. Спасибо.

У вас коннекшены в jdbc не закрываются ....

Почему же, в main’e в finally у меня есть connectionManager.close(); Т.е. закрываю 1 раз в самом конце. Или так не хорошо? А вот за хибернейт — да. Там куда-то мой close потерялся :(

Почему же. В main’e в finally у меня есть connectionManager.close(); Т.е. закрываю 1 раз в самом конце. Или так не хорошо? А вот за хибернейт — да. Там куда-то мой close потерялся :(

Вот тут вы не закрываете коннекшены: github.com/...JDBC/JDBCFormDAOImpl.java

Если я дерну, например, метод findFormById, то коннешен создаться, но не закроется никогда.

Решил посмотреть твой проект, т.к. сам пользуюсь своим самописным плеером. Небольшое напутствие: пока твой проект очень маленький, но ты можешь развить его до почти полноценного плеера, которым сам сможешь пользоваться. А пользоваться своим же софтом — это крайне приятная штука. Для низкоуровневой «проигрывающей» части я использовал библиотеку BASS, это весьма мощная либа, она позволит проигрывать mp3, ogg,
wav и при желании всякие flac, wma и т.д. Она даже делает преобразование Фурье для текущего сигнала, на основании которого можно делать всякие анимации (типа прыгающих в такт ’столбиков’ как в винампе). Дальше работа с плейлистом: добавить (в том числе и drag&drop), удалить, сохранить/загрузить, менять позиции трэков, подсвечивать играющий трэк и т.д.
Эквалайзер (BASS позволяет). Возможность сворачивать плеер в трей плюс горячие клавиши для управления для всего (вплоть до изменения громкости) — очень удобная штука.
А теперь замечания по твоему коду. Использование MVP это хорошо. Что мне не понравилось или точнее что сразу кидается в глаза.
— частичное отсутствие модификаторов доступа. Проставь их везде (на методы и проперти/поля), даже в местах где очевидно подходят дефолтные значения.
— будь последователен в именовании полей, используй _ для всех приватный полей (В классе MainPresenter про random & info).
— именование методов, _mainForm_PrevTrackClick — выглядит уродливо, обычно методы именуются в CamelCase. Т.е. MainForm_PrevTrackClick. Eсли это была попытка выделить приватные методы тогда используй #region Private methods
— последовательность в количестве new line после методов и классов. Одна пустая строка после метода/класса/интерфейса/структуры — хорошо, отсутствие пустой строки — плохо. Использование обоих вариантов — тем более плохо.
— паблик проперти должны идти с большой буквы, totalMinutes -> TotalMinutes
— при определении класса обычно сначала идут приватные поля, потом паблик проперти/ивенты,
потом конструктор, потом паблик методы и потом приватные методы. Можно использовать #region при желании (если класс большой). В MainForm все в перемешку.
— обычно вспомогательные/мелкие классы/структуры идут первыми. Т.е. в MainForm.cs я бы ReceivedDataEventArgs поставил перед MainForm. Также и в CommandManager.cs.
— OnTimedEvent, если проверяешь InvokeRequired то нужно дописывать и else с прямым модифицированем trackBar.Value
— что-то по всему проекту я не вижу не единого try/catch. Что если будет какой-то битый mp3? Можно было бы хотя бы messagebox юзеру показать, а так завалится наверное все приложение.
Пожалуй пока хватит. Может некоторые вещи могут показаться субъективными, но во всех проектах где я работал это считалось хорошим тоном, поэтому и я так считаю.

Добрый день, хотелось бы услышать полезную критику в свою сторону по следующему коду:

1)Вопросы, ответы, регистрация, профиль, лайки
2)github.com/P1sar/QuAsker, p1sar.pythonanywhere.com
3)#Flask, #Python, #sqlalchemy

Маленька порада. Для комітів варто давати більш змістовні і конкретизовані тайтли.

1. Внешние библиотеки (т. н. вендорские) не должны быть в репозитории — что будешь делать, если Bootstrap обновится или обнаружат критическую багу в jQuery?
2. .pyc в репозитории? Серьезно?
3. Я даже невооруженным глазом с планшета вижу, что код не по PEP8 и flake8 выдаст кучу ошибок.
4. Во вьюхах творится угар и содомия. Вынести как минимум кусок авторизации в отдельный блупринт в модуль (если помозговать, можно еще повыносить чего), разнести вспомогательные компоненты в нужные файлы.
5. У тебя на сервере конфиги точно такие, как и на локалхосте: с дебагом, secret keys, и прочими секретными вещами. Небезопасно, правда?

Спасибо за потраченное время) Это мое первое приложение поэтому иллюзий я не питал)
Я так понимаю план минимум который необходимо сделать:
1)Поправить репозиторий
2)Проверить код на соответствие PEP
3) Разобраться с блупринтами (Насколько я понял разбить view на несколько модулей)
4)Поправить конфиг
Возможно ли тогда получить более детальный review ?

Ты пропустил № 1, с которым скорее всего будет сложно бороться (подсказка: npm + grunt/gulp/webpack). Ну и еще прикрутить нормальный flask-migrate (который у тебя уже в зависимости) вместо скопированных скриптов с мега-туториала. А там можно будет и посмотреть глубже

Доброго дня, уважаемые гуру разработки
буду благодарен за ревью моего небольшого класса, который вытаскивает информацию о расстоянии между двумя точками через Google API
github.com/...e/DistanceCalculator.java

1. Просить проверить 50 строчек кода/1 функцию не стоит (ибо смотреть нечего), сделай лучше полноценный небольшой проект
2. Погугли на тему unit-testing, в частности assert() - вместо ручной сверки следует проверять так
3. Сам не Джавист, но парсишь JSON странно: почему сразу не достать значение вместо присваиваний?

1. можно попробовать и так
2. юнит-тесты я знаю. в класс вставил пару выводов для smoke-тестирования
3. Я не знаю как сразу достать в джаве значения из вложенного json. примеры, что я нашел показывают только как доставать объекты первого уровня вложенности, поэтому пришлось писать цепочку касаний

1. Из calculateDistance вынеси парсинг JSON в отдельный метод;
2. Для хранения, вставки и выдергивания по ключу параметров используй Map<string ,="" string=""> params = new HashMap<string, string="">.
3. Создай еще один метод, который бы формировал запрос на основании созданной Map<>.
4. Создай класс специфических ошибок (extends RunTimeException) для класса DistanceCalculator и кидай их в соответствующих методах.
5. Напиши юнит-тесты, такие проверки никто не делает

Используй библиотеку Jackson for JSON.

Посмотрел. Мысли.
1) getJson можно перереписать без использования return String. А работать на уровне интерфейса Reader. Это и экономно и признак профи.
2) В корне неверная логика отработки Exceptions. Если у вас в строке формирования url выбрасывается любой Exception то выполнение потока логики продолжается хотя по смыслу нужен возврат наверх.В результате в скрин выбрасываются новые ошибки класса NPE которые уже безсмысленны и являются просто следствием первого исключения.
3) Для семёрки и восьмерки можно использовать try-with-resources. Это улучшает код.
4) Работа с библиотекой simple-json выглядит корявенько. Есть предположение что лучше просто взять любую другую и попробовать с ней. Может будет меньше букв.

1. Шаблон для реактивного рест сервиса на Scala и Play2 Framework
2. github.com/...ev/reactive-rest-template
3. #play#scala

Первое что мне бросается в глаза это то что вы в своих утиль трейтах которые экстендятсья от Контроллера делаете запросы в базу (github.com/...RESTController.scala#L25. Я просто тут бы сделал нормальную модель и в ней хранил бы все методы работой с базой. Типо как тут: github.com/...models/ReportsModel.scala

Вот тут вы что то как то нагромоздили ошибки в фьючерс success github.com/...tRESTController.scala#L43 , может лучше отдавать ошибку в фьючерсе (Future.exception)? я на самом деле немного не понимаю смысл этого трейта с методами. Такое чувство что вы бы могли немного разнести логику по разным обьектам.

Наверное вот эта каша в вашем Трейте-Контролере-Моделе вылезла из-за того что вы смешали все в месте.

Пожалуйста вынесите работу с базой в Модель (возвращает данные из базы но не содержит бизнес логику) и оставьте бизнес логику в Контролере (возвращает Фьючер).

Так же мне не очень нравится матч на тру \ фолс, я бы тут классический иф \ елс сделал, но это ИМХО.

Так же я думаю вместо ErrorWrapper (github.com/.../utils/ErrorWrapper.scala) можно было бы создать кейс классы нужных вам ошибок с предефайн данными в ним (дефалтовое сообщение о ошибке, HTTP code, etc), типо как тут: github.com/...ions/BaseExceptions.scala

И потом ошибки можно где то раз матчить в одном методе и вернуть правильный Фьючерс с правильным HTTP кодом (честно, не знаю как это в Плее, но в Финатре можно делать так: github.com/...ontrollers/IndexApp.scala вроде более элегантно).

Так же замечание по РЕСТу. Важно возращать правильный HTTP code в зависимости от Экшена: www.restapitutorial.com/httpstatuscodes.html

Так как у вас Контроллеро-Модель всегда возращает либо ошибку либо 200.

Ну и наверное для REST API я бы посоветовал посмотреть либо в Spray (spray.io) либо Finatra от Twitter (finatra.info) — если что для финатры у меня есть проект-пример как ее использовать: github.com/...o/finatra-angular-example

Сори, увидел что там есть 201 и 204.

Тогда осталось обработать HTTP коды для ошибок. А то я так понимаю все ошибки приходят с кодом 500 (InternalServerError) с сообщением о ошибке в JSON. Если ошибку вы обработали сами, то это явно не 500.

Можно использовать для кастомных ответов с кодом ошибки: Status(488)("Strange response type")
От сюда: www.playframework.com/...entation/2.0/ScalaActions

Там уже есть некоторые ошибки, типо 404

от Контроллера делаете запросы в базу
Я правильно понял что более правильным будет сделать сервис который будет дергать DAO? А в самом контроллере работать уже с самим сервисом? Просто я не нашел для себя весомого аргумента чтобы городить уровень сервисов ради того чтобы доставать данные из бд, когда есть готовое DAO.
я на самом деле немного не понимаю смысл этого трейта с методами
Смысл в том чтобы легко создавать стандартные REST контроллеры, а не копипастить код из контроллера в контроллер если будут добавлены новые модели.

Да, правильно понимаете.

Просто если этого не делать, тогда уж можно и без контролерах, чисто из вьюхи запросы в базу делать, чего уж :)

Когда есть четкое разделение, хотя бы MVC, его удобно маштабировать.

Я думаю после того как разнесете модель с контролером, можно будет еще раз сделать код ревью.

еще забыл упомянуть, вы не правильно используете трейты, они не должны быть такими толстыми классами. Про трейты можете почитать тут: www.vasinov.com/blog/scala-oop-galore

One big difference between classes and traits is that traits don’t support constructor parameters but have type parameters. Traits are supposed to be very minimal and focus on one responsibility.

Да, вы правы. трейт DefaultRESTController явно логичнее сделать абстрактным классом.

Так же меня только что осинило что у вас в коде я видел Await: github.com/...ValidationRules.scala#L16

Для продакш аппликух его не желательно использовать, так как он будет блочить — будет ждать ответ. Надо делать все асинхронно с использованием фьючерсов.

О фьючерсах можно почитать:
docs.scala-lang.org/...erviews/core/futures.html
danielwestheide.com/...elcome-to-the-future.html

Доброго времени суток, я в поиске первой работы в качестве Juniors Front-end dev, хотелось бы услышать что у меня так...

1.Прошу прокоментировать моё тестовое задание(angular) — akmil.github.io/...RUD_Kiwi-table/index.html

Задание тут: docs.google.com/...it#heading=h.3lxhdpe81iw3
(только то что в этой папке: github.com/...ee/master/CRUD_Kiwi-table , не весь проект), тестирование не работает(туда не смотрим)
-----------------------
И еще я делал другое задание но по верстке, для css использовал less (первый мой опыт с less), вот финальный вариант: akmil.github.io/...iveTestAstound/index.html

Описание(вообщем-то только псд с 4 пунктами требований): www.dropbox.com/...m7d1n/responsive.psd?dl=0

Исходники:
github.com/...ter/responsiveTestAstound (только то что в этой папке не весь проект)

По CRUD.

Очень плохо что не продемонстрирована работа с асинхронными событиями на должном уровне. Скажем, в реальности список пользователей возвращался бы как promise. Не выполнено требование задания «angular mock».

В userDAO зачем-то набросана обработка UI сообщений. Сервисы и вообще компоненты должны заниматься одной вещью.

В tableCtrl scope используется как большая свалка. Особенно характерно добавление DAO сервиса в scope и использование его напрямую из view. Налицо непонимание разделения обязанностей. Недостаточно продемонстрировано умение выделить связанные вещи в отдельные компоненты (пагинация, модальный диалог лучше бы смотрелись отдельно).

Странно что мета-информация полей сущности пользователь задаются для диалога создания пользователя, но те же поля захардкожены в списках. Как-то логично или все хардкодить или использовать мета-описание.

«Вывод пользователя должен производиться с использованием directive.» — не выполнено.

По коду

$scope.users.forEach(function(users, _index) { if (users.index === row.index) { $scope.users.splice(_index, 1); } });

можно было бы заменить простым

$scope.users = $scope.users.filter(function(x) { return x.index !== row.index; });

опять же, для forEach, есть angular.each(iteratedScope, function(key, value){});

Добрый день, буду благодарен, если сможете поревьюить код моего приложения для андроид. Приложение сделано для людей изучающих немецкий язык. Пользователь сам добавляет, редактирует и удаляет слова. Пользователь выполняет «урок», в котором имеется три возможных типа задания: для повторения глагола, существительного и задание на перевод. Ссылка на репо github.com/olyv/WortschatzGradle

А если вам это приложение пригодится, то вот ссылка на маркет play.google.com/...id=com.olyv.wortschatz.ui

Добавил веб версию wortschatz-olyv.rhcloud.com, логин и добавление слов добавлю позже :)

зачем ты хранишь готовые ответы в js?

Спасибо за комментарий. Я получаю json со всеми словами с бэк-энда, ангуляр отвечает за логику проверки. Предпочтительнее будет выполнять асинхронный запрос для проверки каждого слова? Я просто думал нынешний подход более оптимальный. Или я ошибаюсь?

можна я на твоем длинном линке потренирую своего бота, вдруг кто то с телефона захочет его открыть ? вот B4C код — 1000-164

С опалу написал просьбу подсобить с бодрящим пинком в другом топике, хотя следовало было сюда.

Исходные данные:
bitbucket.org/cybran/e-library — почти половина копипаст от другой половины; делал на скорую руку
bitbucket.org/cybran/chatie — простой чат с подпиской на каналы
github.com/...Cybran111/Learning-system — дипломный проект (еще в разработке). Пытаюсь делать по TDD, но Селениум напряжно дается вследствии повышеной ’рутинности’
github.com/...ybran111/FortyTwoTestTask — простенькая аппликуха

Делал еще парсер на несколько сайтов, из которых нужно было вытянуть теги напрямую из мп3 файлов; распараллелил, делегировав процесс выкачивания заголовков мп3 и их парсинг в Celery (т.к. файлов over 9000). Показать код не могу т.к. под NDA (делал на одеске).

Читал Dive into Python, TDD with Python, кучу блогов на разные темы, прошел курсы Седжвика по алгоритмам. БД знаю на уровне простеньких запросов с join’ами и транзакции, немного работал с MongoDB, читал про Redis, но не пользовался.

Так вот, что мне следует еще изучить к этому набору? Думаю копать в сторону data science, но как для junior’а без работы это будет лишним.

линки на гитхаб битые

Доброе время суток всем, снова:)
В прошлый раз собрав рекомендации по исправлению моего кода, я старалась привести его в более менее читабельный вид. Так как требования в разных компаниях немного отличаются, некоторые требуют jsp/servlets, другие же spring, я сделала оба варианта, они одинаковы больше чем на половину, но цель была показать использование технологий, и вот что получилось:
Spring, Thymeleaf github.com/Jan90/Shop1
JSP,Servlets github.com/Jan90/Shop2
Если кто-то будет запускать код, то должно запуститься с базой, пишите, если скриптлет не срабатывает, попробую исправить.
Обратите внимание пожалуйста на читабельность, это, по слухам, главное умение(ну и алгоритмы еще) которым должен обладать человек который хочет попасть на работу.

В процессе создание данного кода возникли пару вопросов:

1. Сессий в Spring для меня пока непонятны, если в сервлетах вроде бы все понятно, находятся сессии в сервлетах, устанавливать их через setAttribute, а доставать через getAttribute, и использовать куки если нужно запомнить пользовательские данные на долгое время, то в Spring мне не понятно куда нужно сессии вставлять, в модели их или в контролеры или еще куда-то, может у кого-то есть источник с доступным объяснением этого явления, в доках вроде бы нет, ткните пожалуйста кто знает:)
2.Есть у меня файл github.com/...goriesRepositoryImpl.java и как я думаю ненужный jdbcTemplate, потому что он там нигде не используется, но когда я его удаляю и его сеттер, выдает ошибку при запуске и соответственно ничего не работает, я пробовала исправить делая манипуляции с диспатчером но пока не решила эту задачу, может у кого-то что-то похожее было, подскажите решение:)

Ну и еще несколько вопросов напоследок:
1. Есть легенда что существуют компании которые предпочтут кандидата(без опыта) с хорошим английским (не совсем свободно конечно, но поддержать разговор на простые темы может (не внедряясь в какие-то определенные сферы где нужен определенный набор слов(химия,биология и т.д.), документация почти без проблем), но который на 10-30% меньше имеет техническую базу, кандидату у которого техническая база соответственно на 10-30% больше но английский хуже (разговорный почти на нуле, а чтение документации среднее с использованием переводчика), судя по моему маленькому опыту и опыту пары моих знакомых которые обошли почти все компании которые набирают без опыта, их не существует. Может здесь, кто знает, поделитесь информацией про такие компании :) Желательно те у которых есть офисы в Харькове.

2. Все чаще стали требовать знания или понимание паттернов проектирования, их, согласно википедии, много, я скорее всего их не выучу все, и на практике такое нужно учить я считаю, так вот, подскажите два или три таких шаблона которые наиболее часто требуются (про синглтон знаю), чтобы я смогла ответить на такой вопрос если зададут, типа я в теме:)
Всем заранее спасибо за ответы:)

Проблема с шаблонами, что их надо понимать. Когда использовать и когда нет. И как они могут выглядеть. Я вот по факту использую больше всего State (и для понимания FSM), Observer, Factory method. Вот если надо 3, то неплохой практичный вариант) Надо бы ещё что-то оборачивающее, но сложно посоветовать. Ну пусть Decorator, он достаточно прост и таки используется.

Есть легенда что существуют компании которые предпочтут кандидата(без опыта) с хорошим английским
Я бы сказал, что скорее и правда легенда в нынешних условиях, когда начинающих толпы осаждают

особенно те, которые пишут что у них intermediate, а в действительности не знают разницы между i will go shopping tomorrow и i am going shopping tomorrow. А это на уровне слабый begginer знают.

i am going shopping tomorrow
а так реально говорят?

Если не путаю, то «I will».. означает «возможно пойду» а «..going shopping..» означает непосредственно намерение.

ну да, если сильно придираться то I will это 50/50, а to be going to — 90% что сделаешь то что сказал и имеется маленькая вероятность, что этого не сделаешь.

только

i am going shopping tomorrow
и
to be going to
вообще разные конструкции, если что )

В употреблении с первым лицом тут скорее Decisions v Intentions : will/won’t + infinitive => a decision made at the time of speaking, be going to + infinitive => intentions that have already been decided on. Зависит от контекста. И ничего страшного если кто-то не скажет формально определения разницы. У меня уровень выше среднего, но про разницу в смысле prediction не подумал бы получив такой вопрос.

У меня уровень выше среднего
а это уже обнадеживает, значит английский нужен на более высоком уровне, так как Вы не остановили его изучение на уровне чтения документации.

Не очень понятно, как это может обнадеживать. По большому счету само по себе знание английского как языка не так важно, намного важнее коммуникационные навыки, которые начинают перевешивать где-то после lower intermediate. Понимание разницы нюансов в приведенном примере не будет значительным преимуществом в большинстве международных компаний в которых менеджмент не состоит исключительно из носителей английского. Ну кроме может позиций типа technical writer. Умение объяснить — тем более.

По большому счету само по себе знание английского как языка не так важно, намного важнее коммуникационные навыки, которые начинают перевешивать где-то после lower intermediate.
под коммуникацией, Вы имеете ввиду выразить свою мысль на английском, или понять их сленг, жаргон или и то и другое?
Понимание разницы нюансов в приведенном примере не будет значительным преимуществом в большинстве международных компаний в которых менеджмент не состоит исключительно из носителей английского.
это точно, хотя может и с носителями особого преимущества не будет, потому что для некоторые особого внимание не уделяют на знание языка, мне давно моя учительница по английскому сказала что, из-за того что англ. очень распространен, настоящим англичанам, приходится разбирать такие нереальной сложности акценты и неправильно построенные предложения, что наши люди на их фоне очень выгодно выделяются(по крайней мере акцент у наших более разборчивей). И кстати, мне рассказывал знакомый, года 4 назад его друга в командировку в США отправили, так он немного разговорным владел, а техническим свободно, в офисе там он все понимал, но когда они пошли его с городом знакомить, там и началось, сленг, идиомы, говорил что он почти ничего не понимал, кивал и улыбался постоянно. Так что технические навыки учить нужно в первую очередь, а потом и языками заниматься.

Ну или проще как-то так. I will — я пойду (за покупками завтра), I’m going (I go) — я иду за покупками завтра, I’m going to — я собираюсь (за покупками завтра)

Что Вас именно возмутило, предложение или сама конструкция to be going to? Отвечая на Ваш вопрос, да так говорят.

смутила конструкция to be going to без последнего to.

правильно что смутила, т.к. это разные конструкции вообще-то. Но да, используют такую конструкцию

ага, подозреваю автор имелл ввиду to be going to

наверное да, I’m going to go shopping . Но говорят и I’m going shopping tomorrow

to c shopping не используется. Мы используем to когда говорим о каком-то месте или направлении, также если мы говорим о планах на будущее мы не можем использовать going to + герундий, нужно использовать going to+глагол+герундий, здесь подробней nylcenglish.blogspot.com/...012/07/is-it-correct.html ,
т. е. делаем вывод, что это грамматически не верно, если Вы скажете это иностранцу, он конечно поймет, не это будет звучать немного коряво.

Естественно не используется, после to be going to должен быть инфинитив. Но в ответе Никите Любчич ты подтверждаешь его (и мою) догадку что для тебя разница

между i will go shopping tomorrow и i am going shopping tomorrow
является вопросом разницы между конструкциями will + inf. v to be going to + inf. Что показывает на возможно слабое знание предмета и сомнительное право на оценку знаний других по отдельно выбранным и не очень важным правилам.

спросила на форуме для изучающих английский, модератор ответил что можно использовать как пример www.usingenglish.com/...g-and-i-am-going-shopping . Во избежание новых конфликтов, пусть будет His friends are going to learn English вместо того что было.

По спринг приложению.
— самая большая проблема с конкурентным использованием сайта. Запустите сервер и зайдите парой разных пользователей одновременно и посмотрите что будет
— чего вы хотели добиться, используя CopyOnWriteArrayList в корзине? И да, вы его используете неправильно. Смотрите в сторону итераторов в этом классе
— нет проверок пришедших с клиентской стороны параметров и вывода ошибок. Не доверяйте никому. Всегда валидируйте все параметры запросов
— в JS понамешивано JQuery с Dom манипуляцией. Старайтесь использовать один подход в приложении
— не запускал, но это ж одностраничное приложение вроде? Одностраничные приложения делаются не так. Сервер должен отдавать только данные а не куски страницы с разметкой. Не сваливайте в кучу данные и представление. Смотрите в сторону REST
— @Autowired и на поле и на конструкторе не нужно. Достаточно одного
— выносите константы в финальные поля а не пишите просто в коде. Заметил что в паре мест вы так и поступили, а дальше что, лень? )
— 

@ResponseBody void
и это работает? О_о ... первый раз такое вижу )))

ну как-то так для начала

вау, уже и не надеялась здесь кого-то дождаться, спасибо:)

в JS понамешивано JQuery с Dom манипуляцией. Старайтесь использовать один подход в приложении
т.е. var currentColor = document.getElementById('menu').style.backgroundColor; убрать, а заметить на jquery типа такого, $.each(genres, function(index, value) { $("#genre").append($("<option />").text(value.genre)); }); } правильно?
не запускал, но это ж одностраничное приложение вроде?
нет, там 3 страницы, в readme написано, меню и верх должны быть статичные а контент должен перезагружаться. Поэтому и куски. Так что пусть будут или переделывать?
Не сваливайте в кучу данные и представление. Смотрите в сторону REST
эээ, это html файл и что еще? немного посмотрела про REST , я старалась сделать примерно такое, только рефакторить немножко нужно, можно поподробней что не так, может статичными все html страницы сделать?
выносите константы в финальные поля а не пишите просто в коде. Заметил что в паре мест вы так и поступили,
это вот здесь единичка? или еще где-то?
public CD(String name, String type, String genre) { cdName = name; cdType = type; cdGenre = genre; cdQuantity = 1; }
и это работает? О_о ... первый раз такое вижу )))
я сама немного в шоке, это в инете такой способ нашла, по другому оно не отсылается вообще клиенту, на клиенте, я его через jquery принимаю, думаю от туда и ноги растут, я с ним почти 4 дня провозилась пока поняла что сервер нормально данные не отсылает, если Вы знаете более нормальный способ отправки или может его принять по другому нужно, то скажите:)
нет проверок пришедших с клиентской стороны параметров и вывода ошибок. Не доверяйте никому. Всегда валидируйте все параметры запросов
на null проверять и все?
его вы хотели добиться, используя CopyOnWriteArrayList в корзине?
убрать и поставить ArrayList?
А что с четабельностью, нормальная?
т.е. var currentColor = ...
я не вникал что делает код, просто выберите, или вы работаете только через jquery или только через document. Смешивание усложнит дальнейшее развитие и поддержку.
нет, там 3 страницы ...
поищите что такое single page application. Это принцип построения приложения с точки зрения архитектуры а не количество страниц в нем. Если задача менять контент но чтоб меню было статично — то это оно. Но делается не так. С сервера должны приходить только данные (например в формате JSON) а не кусок HTML разметки с данными там (отделяйте данные от их внешнего вида). А уже JS на клиенте должен обновить часть страницы и вставить данные куда надо. Сервер (джава) работает с данными и ничего не знает о внешнем виде страниц, JS на клиенте подставляет данные куда надо и переключает шаблоны HTML , который, в свою очередь, занимается форматированием.
сервер нормально данные не отсылает
там же метод возвращает void. Какие данные вы от него хотите то?
на null проверять и все?
нет конечно. Что будет если я пошлю запрос на удаление товара из корзины с индексом −1 ?
убрать и поставить ArrayList?
нет, разобраться в чем разница и понимать когда и что нужно использовать (и как).

Ну читабельность ок, но вот задумайтесь о первом моем замечании в первом комменте. Это главное. И разберитесь и переделайте. Если все остальное мелочи, то проблемы с синхронизацией делают приложение вообще неработоспособным

поищите что такое single page application.
нужно было сделать все с помощью Angularjs?

я переделала все с Angularjs. Посмотрите пожалуйста github.com/...tree/master/Shop/src/main . Некрасиво, на мой взгляд, получилось то, что все на сервере нужно в json конвертировать, это так и должно быть или есть более компактный способ конвертирования? Еще контроллеров получилось на два файла больше, хотелось бы их в три файла вместить, но не получается и выглядят они не совсем так как хотелось, вот они github.com/...r/Shop/src/main/webapp/js , у меня есть два варианта как сделать контролеры более презентабельными, первый это вместить их в три файла, это реально? потому что у меня сложилось впечатление что нет. И второй вариант, более реальный для меня, это сделать еще больше контроллеров, один контроллер на 1-2 функции, и соответственно создать больше файлов, но не будет ли это некорректным? И еще последний вопрос, там где переключаются страницы я сделала через ссылки, но в некоторых примерах предлагают делать с помощью директив, вот я и не пойму, оставить с ссылками можно или сделать с директивами?

Некрасиво, на мой взгляд, получилось то, что все на сервере нужно в json конвертировать, это так и должно быть или есть более компактный способ конвертирования?
это зло. Посмотрите что такое, например, Jackson и переделайте. Никому такое преобразование в json не показывайте )

я не эксперт в энгуларе, так что по нему на вопросы не отвечу. Много мелких контроллеров не страшно. Главное логически разделить и называть нормально. Лучше мелкие контроллеры чем монстры, которые делают все.

чего вы хотели добиться, используя CopyOnWriteArrayList в корзине? И да, вы его используете неправильно. Смотрите в сторону итераторов в этом классе
нет, разобраться в чем разница и понимать когда и что нужно использовать (и как).
CopyOnWriteArrayList потокобезопасная коллекция, должен использоваться в многопоточной среде, и создает при итерации не изменяющуюся копию массива, в то время как записывающий поток может записать значение в массив. Лучше использовать там где массив используется больше для чтения чем для записи. А зачем мне CopyOnWriteArrayList я не совсем понимаю, он же в run должен быть, а у меня run нет. Наверное его убрать нужно?

CopyOnWriteArrayList, во первых, создает копии для итераторов а не для использования доступа по индексам.
Во вторых, я вижу что у Вас отсутствуют базовые знания в вопросах многопоточности. Если хотите действительно понимать многопоточность, очень советую к прочтению Java Concurrency in Practice от Brian Goetz. Это просто маст хев.
Говоря об этом конкретном кейсе, потокобезопасные коллекции использовать в корзине нет никакого смысла, просто корзина должна быть в сессии, и использоваться только в одним потоком в каждый момент времени.

@ResponseBody void

а что в этом выражение не нравится ? с @RestController самое то как на меня

ну не то что не нравится, а вообще странно что метод возвращает void и обозначен как @ResponseBody. Обычно если метод ничего не возвращает а должен вернуть только 200-й код, то аннотируется он по другому. Такого никогда не встречал

Запустите сервер и зайдите парой разных пользователей одновременно и посмотрите что будет
здесь была проблема в сессиях? Если заходить с разных пользователей то корзина у них получалась одна на двоих.

корзина должна в сессии храниться. Важнее понимать почему

потому что мы хотим сохранить уникальные данные о пользователе, идентифицировать его и послать ему его данные? Еще, я где то читала, что если создавать сессию не только в корзине, а и по всему сайту, то это очень ресурсозатратно.

да, у каждого пользователя своя сессия.
Что значит «создавать сессию по всему сайту»? Думайте о сессии как о шкафчике в бассейне. Вы пришли, показали пропуск, вам дали шкафчик. Пока вы в спорткомплексе, вы им пользуетесь, кладете туда свои вещи и тп. А ушли — шкафчика у вас уже нет. Когда в бассейн придут несколько посетителей одновременно, то им дадут разные шкафчики и конфликта не будет. Ну и каждый посетитель получает ключ от шкафчика когда показывает пропуск на ресепшене. Так же и сессия создается при аутентификации пользователя. По этому нет такого «создавать сессию по всему сайту»

спасибо, уже почти все переделала возникло пару вопросов

if (dvd.getName().equals(newItem.getName())) {
dvd.setQuantity();
+ //TODO: important mistake that demonstrates lack of understanding how objects and memory allocation works
+ // in java. You don’t have to set back the same object that already sits in the collection that place.
items.set(i, dvd);

вот здесь я изменяю количество продуктов(dvd.setQuantity();) в dvd, и потом с новым значением количества продуктов перезаписываю старое значение, которое вмещает в себя уже не актуальное количество продуктов, новым(items.set(i, dvd);), но все прочие параметры кроме количества остались прежними, вопрос: почему они одинаковые если они имеют разные показатели количества? Или под «одинаковые» имеется ввиду индекс где они находятся?
//TODO: DAO should not know how exactly is it used on the presentation side. No Drop-downs here. Same for the service.
public List<string> populateDropDownList(String type) {
нужно только переименовать метод, или его убрать из dao вообще?
+//TODO: this server doesn’t seem to do anything.
public class StoreServiceImpl implements StoreService {
он наверное ничего и не должен делать, это я хотела сделать сервис слой, как посредник между dao и сервлетом. Его убрать? Пусть сервлет обращается напрямую к dao?
почему они одинаковые если они имеют разные показатели количества?
Проведем мысленный эксперимент :
List<CD> cds = Arrays.asList(new CD()); CD cd = cds.get(0); cd.setQuantity(); assertEquals(1, cds.get(0).getQuantity());

упадет тест или нет, и почему?

так как мы говорим о корзине, упадет, потому что в конструкторе по умолчанию количество было 1, мы в cd.setQuantity(); добавили к количеству еще 1. и в итоге будет уже 2. На этом этапе вроде бы понятно, мы получаем копию значения через cds.get(0) и изменяем в ней значение количества, но потом нам его нужно заново записать на место того показателя с которого мы сделали эту копию, она же сама не обновится не может, вроде бы. Вот если б мы получали не копию, а оригинал, через cds.get(0), мне бы тогда было понятней почему это два одинаковых объекта. Я, наверное, не там ищу причину?

это в другом конструкторе будет 1 по умолчанию, в этом — 0 (что кстати тоже грубейшая погрешность). Потом добавляется 1. Вопрос с другой стороны — сколько объектов типа CD создается в выше приведенном коде?

создается один, наверное я поняла, в куче мы изменяем значение и в коллекцию перезаписывать не нужно, оно уже там. Правильно?

(что кстати тоже грубейшая погрешность)
спс, исправлю.

Тесты тоже кстати не ахти. Большинство тестируют работу гетеров/сеттеров, нарушается правило одной проверки на тест, mvn test падает по зависимостям, в pom.xml жуткое форматирование.

Привет всем!
Сижу, изучаю JavaEE и прочее вокруг, изобретая очередной велосипед-стартап.
Очень нужна помощь в небольшом код-ревью. Я хочу понять как лучше писать с точки зрения архитектуры и использования нужных технологий. Особенно интересно послушать про реализацию REST-слоя.

Цель этого велосипеда это бекенд к Андроид-приложению.
Используется postgres+wildfly+rest.
Джависты, посмотрите, накидайте коментов что где было бы лучше и что почитать на эту тему.
Если возможно хотелось бы получить пример рабочего кода по REST или хороший пример на гитхабе.
А также ресурсы, специализированые для таких вопросов.

Хотелось бы уже вначале карьеры поменьше быдлокода генерить.
Сылка на гит: github.com/demoontz/h2
Ключевой ворос- Архитектура и REST слой.

Спасибо!

Могу порекомендовать Spring Data Rest

Код откровенно плоховат.
* не используйте непонятные либы типа code.google.com/p/generic-dao (com.szczytowski.genericdao) . Или мейнстрим или свое.
* org.demoon.h2.dao.UserDAO#getUserByLoginPass и везде — опускать фигурные скобки в if/else является очень дурным тоном.
* org.demoon.h2.mechanic.Except нарушает стандартное соглашение об именовании исключений (имя класса должно заканчиваться на Exception).
* Там же — по возможности лучше минимизировать использование и наследование от checked exception. Что, впрочем, может оспариваться.
* Там же — не оставляй ненужных стабов (конструкторы)
* Там же — в базовом классе уже есть сообщение, если занимаешься наследованием — старайся не дублировать поля.
* org.demoon.h2.mechanic.Except создаются с кодами, которые задаются как magic numbers. Обычно в java мы или создаем иерархию custom exceptions или задаем enum с типом ошибки или хотя бы определяем коды как константы в одном хорошо известном месте.
* org.demoon.h2.mechanic.UserMech — название класа загадочно.
* в логине, создание инстанса User чтобы передать в org.demoon.h2.dao.UserDAO#getUserByLoginPass пароль и логин — очень странное решение. Передай просто два строковых параметра, будет чисто и понятно. Тем более другие методы принимают строки и именно нужные.
* там же — переиспользование переменных — это грех.
* org.demoon.h2.mechanic.UserMech#modifyPass — что будет если org.demoon.h2.dao.UserDAO#getUserBySTag вернет null ?
* rest.json.v0.Error — ужасен полностью. Во-первых не совсем понятно его предназначение — он кажется во многом дублирует уже виденный нами Except. rest.json.v0.Error#lisrEgorkas — нужно переосмыслить имя метода, сделать его статическим и вызывать один раз в жизни. Так же в строках 47-50 делается четыре поиска в хеше вместо одного.
* Весьма спорное гашение исключения в rest.json.v0.UserRest#update . И в целом логика.
* rest.json.v0.Utitlity#isNotNull — метод делает не то, что обещает названием.
* rest.json.v0.Utitlity#constructJSON(java.lang.String, boolean) и rest.json.v0.Utitlity#constructJSON(java.lang.String, boolean, java.lang.String) — повторяют друг друга. Лучше унифицировать, например вызывая второй из первого с нулевым последним параметром.

Я внес почти все исправления, есть пару но.
-непонятная либа типа code.google.com/p/generic-dao (com.szczytowski.genericdao) единственная которая завелсь без спринга. Мейнстрим как я понимаю эта code.google.com/p/hibernate-generic-dao. ее я запустить не смог. требует замены аннотаций.
— best practice с работой с ошибками я не нашел. поэтому пока катаюсь на своем велосипеде. хотя насправлял там массу.

Прошу еще раз сделть код ревью.
Спасибо!

зы. я постоянно имею сомнения относительно работы с WildFly и EJB. все работают с Spring, а я вот нет. Может стоит пересмотреть технологии пока не поздно?

Принципиально не поменялось. Со списком ошибок стало еще хуже. Он все равно создается для каждого инстанса класса, и сохраняется в статическую переменную.

непонятная либа типа code.google.com/p/generic-dao (com.szczytowski.genericdao) единственная которая завелсь без спринга.
она не очень нужна если посмотреть на то, что из нее используется. Hibernate/JPA достаточно развиты чтобы их пользовать напрямую или оборачивать мелкими кастомными утилитками. ИМХО.
best practice с работой с ошибками я не нашел.
наверное стоит почитать хорошее введение в Java. Thinking in java или подобное.
все работают с Spring, а я вот нет.
специально вопрос не изучал, но как-то мне лично все время только Спринг попадается. Про EJB в основном в связи с банками слышать приходится да и то редко.

Добрый день! Получил недавно тестовое задание на позицию Java Apprentice.

Необходимо реализовать http-сервер на фреймворке netty
( netty.io ), c функционалом:

1. По запросу на http://somedomain/hello отдает «Hello World» через 10 секунд
2. По запросу на http://somedomain/redirect?url=<url> происходит
переадресация на указанный url
3. По запросу на http://somedomain/status выдается статистика:
— общее количество запросов
— количество уникальных запросов (по одному на IP)
— счетчик запросов на каждый IP в виде таблицы с колонкам и IP,
кол-во запросов, время последнего запроса
— количество переадресаций по url’ам в виде таблицы, с колонками
url, кол-во переадресация
— количество соединений, открытых в данный момент
— в виде таблицы лог из 16 последних обработанных соединений, колонки
src_ip, URI, timestamp, sent_bytes, received_bytes, speed (bytes/sec)

На задание дали 5 суток. Выполнил в срок, задание на 100% рабочее.
Скриншоты страниц и бенчмарка и, конечно же, код здесь:
github.com/Alex-e/nettyServer

По заданию сказали, что не прошел. Попросил прокомментировать код, но ответа не получил. Я потратил 50+ часов, изучил новый фреймворк. Теперь хочу понять, что сделал не так. Может, баг какой-то вылез, а может, архитектура кривая, да и мало ли что. Подскажите, пожалуйста, для меня это важно. Заранее благодарен!

Дай угадаю, лого фирмы это хомяк?)

На какую позицию претендовал? Джуниор или Синиор?

и сколько лет опыта программирования/java

Добрый день! Получил недавно тестовое задание на позицию Java Apprentice.
это вроде джуна я думаю. Опыта коммерческого 6 мес. Интересует ревью если кто-то может мне подсказать мой косяк с сервером.

Да все там плохо, но как для джуна нулящего, то могло бы и быть простительно. То что не отписали более детально причину непрохождения — это конечно свинство. Порадовало название класса «WrapperOfEverything» — годный троллинг :)

А можно подробнее, почему все плохо?

можно. Если не закроют топик к концу недели — постараюсь откомментить (хотя сам с конкретно netty тоже не знаком).
Из бросившегося в глаза в добавок к @Dmitry Chaban:
* имя пакета «UriHandlers» — за заглавные будут сильно по рукам бить
* бестолковое распределение обязанностей между HttpHandler и UriHandler. Зачем StringBuffer в интерфейсе UriHandler? Чтобы HttpHandler создал его и пустого передал? Проще было бы в самих UriHandlerах выбирать как создавать строки, тем более они все кроме одного статические — объяви строковую константу да пуляй себе.
* Хэндлеры кроме статистики — stateless. Да и тот можно было бы сделать передавая контекст в интерфейсный метод. Stateless — это хорошо, можно объявить как константы и не создавать новые объекты.

бестолковое распределение обязанностей между HttpHandler и UriHandler. Зачем StringBuffer в интерфейсе UriHandler? Чтобы HttpHandler создал его и пустого передал?
каюсь это я из какого-то туториала по нетти взял.
По поводу stateless отличная мысль. Спасибо. Пойду рефакторить.

добавил немного комментов как пулл риквест. github.com/...Alex-e/nettyServer/pull/1

побольше бы таких ревьюеров как вы!

Просмотрел наискосок через строчку:
— в константы кучу переменных вынести надо
— атомики кажется не уместны местами
— WrapperOfEverething — тупое имя, как и имя пакета, остальные классы внутри него тоже не -созвучны с этим пакетом
— LoggingQueue может просто так терять записи, зачем она такая нужна? вообще для — этой логики есть другие кошерные решения
— потоки всегда нужно закрывать в finally
— хорошо бы добавить какое-то логирование, например sl4j, + во всех try-catch логировать обработку исколючений
— if-else всегда писать с фигурными скобками
— и т.д. и т.п.
Открыл из-за любопытства к netty, я с ним не знаком, но по ощущениям он не очень правильно используется.
Вообще как для

Apprentice
мне кажется не плохо.
— LoggingQueue может просто так терять записи
вот это меня больше всего интересует. А в какой момент она может их терять? единственное место где добавляются данные это синхронизированный по LoggingQueue кусок метода в синглтоне (StatisticsHandler)

Ну вам там 16 элементов нужно, а у вас удаление происходит когда их больше 15, и do while мне не нравиться, он же только после удаления размер проверит... + когда из очереди элементы будут доставать :)
По идеи если у вас больше 16 элементов, и все общение из синхронизированого метода, то вам на каждую вставку одного нового элемента достаточно просто удалить 1 старый, но потенциально если в это время один элемент из очереди достанут, то удаление может быть лишним.
В Guava есть EvictingQueue которая сама будет удалять старые элементы, она thread safe и не блокирующая, так что думаю с ней можно будет убрать синхроназед блок и тогда будет работать быстрее и безопасно.

Class EvictingQueue<e>
A non-blocking queue which automatically evicts elements from the head of the queue when attempting to add new elements onto the queue and it is full.
This class is not thread-safe! Так что это решение явно не более кошерное учитывая что ConcurrentModificationException так и посыпались от конкурентного доступа к итератору.
LoggingQueue не идеальна в своём API и узкоспециализирована. Но она выполняет свою функцию. За 100000 запросов в 100 потоков do while так и не прошел более 1 цикла. Он запускается после проверки size в методе add. Так что в нем нет ничего страшного. И вообще он добавлен был для подстраховки.

+ когда из очереди элементы будут доставать :)
а доставать элементы никто и не будет, только итерация. Для этих целей я бы разработал другую реализацию коллекции.
Кстати, if-else без скобок я научился у Седжвика на курсах, он так все время делает. Говорит что это элегантный код, хотя может на реальной работе мне за это по рукам и дадут ))
Но в любом случае спасибо что откликнулись!
ПС: Хотя может я плохо искал и в гуаве есть другие решения. пойду гляну.

Да, EvictingQueue действительно не thread safe, как-то проглядел, сори. do-while там по идеи вообще безсмысленен.
Из Guava может подойти concurrentlinkedhashmap, но надо посмотреть как она будет вести себя при вставке повторяющихся елементов, так что не уверен на 100% что она подойдет. Вообще есть много способов написать такой cache, можете погуглить к примеру lru cache если будет интересно. Конкретно ваш вариант в вашем случае будет работать, но в реально жизни его кто-то со временем сломает или будет использовать как нельзя. К примеру, если бы вы написали свой интерфейс для этого кеша с 2 методами, сделали бы там где надо синхронайзед + final, а внутри использовали бы просто масив все было бы вполне норм. :)
Код я просматривал не в IDE, и не очень подробно, так что может что-то еще не заметил, может хорошего, а может и плохого.:)

Открыл из-за любопытства к netty

Если хотите ознакомится с нетти на реальном примере — github.com/blynkkk/blynk-server. Это опен-сорс сервер для коммерческого проекта. Описание на гитхабе. Протокол бинарный. Сейчас хендлит около 20к рек-сек на 2 ядрах. Ну и за ревью конечно буду благодарен.

Поковыряюсь как будет время, пока могу посоветовать почитать про isdebugenabled в log4j.
К примеру, можно полностью игнорить GlobalStats.log(..) в случае если дебаг не включен.
И я подумал бы на тему, если в StringUtils.fetchPin() пин всегда есть, + в зависимости от его длины, то индекс поиска можно сразу можно брать START_INDEX + длина пина.
Пока еще не понял зачем нужен GraphInMemoryStorage.java, вроде туда данные кладут, но не нашел где их используют.

Поковыряюсь как будет время
Спасибо.
можно полностью игнорить GlobalStats.log(..)
Глобал статы я использую для мониторинга нагрузки на сервер в реалтайме, чтобы в случае чего, понизить req/sec для юзеров.
StringUtils.fetchPin() пин всегда есть
Он должен быть всегда. Но будет ли — не понятно. Так как наши либы может любой изменить и следовательно прислать, что угодно.

Приложение для дружбы со своими деньгами)
github.com/AnnaLozytska/MoneyMan
Если ревьювить слишком много, то прошу только посмотреть и подсказать как улучшить:
1) UI/UX MainActivity
2) жизнь FragmentUniList-ов в MainActivity (в частности, костыли по подбору высоты ListView и то, как они появляются и исчезают в MainActivity)
3) лоадеры и их производительность (особенно DataFromDBLoader)
4) общую стилистику кода
#Android#Java
Спасибо!)

Мабуть коментарі в коді писати російськю не дуже розмуно. Дотримуйтесь єдиного стайл гайду щодо форматування коду та іменування (маєте зайві пробіли). Окремо винесіть тести, щоб структура була десь — /source та окремо /test. Окремі частини коду у метода, які Ви виділили кометарями є чудовими кандидатами, щоб винести у окремий метод, як настлідок загальний метод буде більш зрозумілімий, тестувати простіше та коментарі будуть зайві оскільки від назви метода буде все зрозуміло, що він виконує.

Додатково до минулого мого коментаря
Намагайтесь уникати хардкоду, наприклад : У вас є таке обчислення у коді (24 * 60 * 60 * 1000), яке повторюється кілька разів. Я думаю варто винести в окрему константу, в результаті константа буде закешована і не потрібно буде два рази обчислювати та якщо буде необхідно змінити значення, то простіше змінити в одному місці, а не в кожному полі де зустрічається цей вираз. Також можливо має сенс копіювати константи в локальні перемінні. На кшалт int static SIZE = 10
foo() { int fooDataSize = SIZE; fooDataBaseSetSize(fooDataSize); } Якось так.

Спасибо большое, Юрий!)) Начинает вырисосвываться план рефакторинга)

Я вам рекомендую книги Роберта Мартина почитать. Для развития именно понимания какой код должен был бы быть.

Общие замечания:
1. Разделяйте логику и UI. Разделяйте вообще все.
2. Код который требует комментариев-по определению хреновый.
3. Метод в котором более 5 строк кода — заслуживает пристального внимания на тему рефакторинга.
4. Закомментированых кусков кода быть вообще не должно.
5. public void SomeMethod() {
...
}
Не ставьте так {}. Это ужасно.
Особенно не делайте вот так
public void SomeMethod() {
}
6. Зачем вам комментарии в xml???
7. Комментарии о том что вы думали и хотели — ужасно. Никогда такого не пишите и никому не показывайте.
8. Отдельно почитайте про CQRS.
9. Избегайте повторов. Избегайте делать одинаковые действия в разных местах разными способами. Навевает мысль на copy-paste без включения головы.

Android не мой домен, потому на специфические технические нюансы не смотрел.

Вот насчет 5-го не понял, что вам не нравится.

Резко ухудшает читаемость

Все равно не понял. Вам не нравится, что скобка в той же строке, что и сигнатура метода? Ну так это, на минутку, официальный code style. Многим (в том числе и мне) он нравится. К тому же, IDE умеют подсвечивать открывающую и закрывающую скобку.

А, ну это да, но у ТС вроде в коде с маленькой.

Да, именно это мне и не нравится. И не всегда есть IDE. Или не такая, как хотелось бы. Или вообще язык другой будет через 2 года. Попробуйте что то на javascript в блокнотике так поредактировать.
Это БОЛЕЕ ЧЕМ ЛОГИЧНО так не делать. Что бы визуально отследить где скобки открылись и закрылись.

Вы, я так понимаю, на C# в оновном пишете? Ну, там да, code convention настаивает на скобке с новой строки. Но мы сейчас говорим о Java под Android, и у Google по этому поводу есть более чем ясное мнение: source.android.com/...yle.html#java-style-rules — смотрите раздел «Use Standard Brace Style».

в блокнотике
Для начала, мы же не собираетесь писать на Java в блокнотике?) Также, надеюсь, вы не имеете в виду notepad.exe. А даже какой-нибудь Notepad++ умеет то же, что я говорил.
Если говорить о JS, то не знаком с их конвенциями, может, там и с новой строчки рекомендуют. Я же говорю только о частном случае, о Java, которая рассматривается в данной ветке.

Котаны, я на десятке языков писать могу, и основной менял 4 раза. Мое сугубое личное мнение, что в C# этот code convention с...а правильный. Впрочем, в Visual Studio об этом можно вообще не думать, все будет сделано за вас.
На чем бы вы не писали.
Я одно время работал с некоторым узкоспециализированным продуктом где была своя IDE и язык с корнями в С. Но не было подсветки скобочек и вообще много чего. Вот там сразу понимаешь, что надо форматировать правильно и как правильно. Как бы это мое личное мнение, а что с этим делать — ваше право.
Есть довольно большое количество ситуаций, когда вам придется работать с кодом вне IDE и без средств подсветки синтаксиса,и тогда это форматирование вам будет не удобно. Но выбор за вами.
p.s. Своему лиду на code review будете доказывать что где то там на заборе что-то написано. Ну как на работу устроитесь :) ну вы понэли? :)

К лиду, который сайт гугла называет забором, я не подойду ближе, чем на километр)
И Android Studio тоже сама скобочки выравнивает, если что. И если ничего не трогать, то согласно тем самым заборным рекомендациям.

я конечно зелен, как лист в маю, но вот так
public void someMethod()
{
...
}
я практически нигде не встречал. Или вы не это имели ввиду?

апдейт, я тоже про Java

Прессовать незамутненых джунов своими личными предпочтениями, идущими в разрез с конвенциями используемых языков... Несолидно.

Это БОЛЕЕ ЧЕМ ЛОГИЧНО так не делать. Что бы визуально отследить где скобки открылись и закрылись.
сугубо дело привычки.

В этом смысле радует Го, в котором эта пища контрпродуктивных споров снята в принципе.

если заглянуть в сорцы джава классов, то можно понять, что
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}

БОЛЕЕ ЧЕМ ЛОГИЧНО

могу поревьюрить Андроид

Посмотрел com/simpleprog/moneyman/MainActivity, вот некоторые замечания:

1. TableLayout tlMainLeft;"
Используйте модификаторы доступа

2. SQLiteDatabase db; Cursor c; DataFromDBLoader dataLoader; public static final int RCCAT = 1; public static final int DATALOADER = 2; long budID;

Константы желательно писать вверху класса, чтобы отделить их от полей

3. tvMainTo = (TextView) findViewById(R.id.tvMainTo); tvMainCurrDate = (TextView) findViewById(R.id.tvMainCurrDate); tvCurDateString = (TextView) findViewById(R.id.tvCurDateString); tvMainBalance = (TextView) findViewById(R.id.tvMainBalance); tvMainBalance.setOnClickListener(this); tvMainFreeBalance = (TextView) findViewById(R.id.tvMainFreeBalance); tvMainFreeBalance.setOnClickListener(this); tvMainDayLimit = (TextView) findViewById(R.id.tvMainDayLimit); tvMainDayLimit.setOnClickListener(this); tvMainDaySpent = (TextView) findViewById(R.id.tvMainDaySpent); ....

У вас много полей которые подписываются на onClickListener в коде, что как по мне можно было бы упростить, добавив атрибут «onClick» в XML в этих views

4. budget.putExtra("calTime", cal.getTimeInMillis());
Выносите константы

Если джава давайте че-нибудь поревьюирую

Здравстуйте.

«Веб продуктовый магазин».
GitHub (слабонервным не смотреть).
#Java#Spring#Hibernate#JSP#MySQL#JQuery#JUnit

Спасибо.

* Проглоченные исключения — это очень плохо. На грани фола. Целых два увидел.
* Лучше все-таки простую фильтрацию делать на стороне базы данных, а то итерация по всем ордерам (которые называются корзинами) чтобы найти незаказанный — выглядит несерьезно.
* Сомнительное как по мне решение делать ордер и корзину одной сущностью. В реальности они отличаются многим.
* В нескольких местах повторяется логика поиска айтемов из корзины.
* ИМХО если уж делать секьюрити то надежнее через что-то типа Spring Security. Геморнее, но в будущем пригодится. Или не делать вообще.

Вот моя поделка известного сайта “Русский Дзен”. Ссылка на репо: github.com/...ee/master/iOS/RussianDzen
#iOS#CocoaTouch#Objective-C

1. Зачем в классе плеера следующее свойство — nameOfFile?
2. Возможно returnSharedInstance стоит заменить на sharedInstance?
3. Возможно Вам стоит использовать #pragma mark
4. stopPlaying метод содержит логирование, playFile — нет. Почему?
5. У вас присутствует дублирование кода (UsefulQuotes, ViewController). Возможно стоит добавить специальные методы / методы-помощники.
6. Возможно Вам будет интересно почитать о SizeClasses.

Насчет #pragma mark проскакивал интересный твит twitter.com/...status/566705401425846272

Тоже самое справедливо и для категорий ;)
То на что ты ссылался, если я правильно понял ( @interface FooClass () ) зовется расширением класса, хотя технически и мало чем отличается от категории.

1) 1, 4, 5 — артефакты от дебага проекта :) действительно, это просто мусор.
2) 2 — сделаю.
3) 6 — о, спасибо. То, чего не хватало. Нужно будет переписать логику изменений длины/ширины labels.

От себя добавлю:
1. Приватные проперти лучше вынести в категорию класса. Или объявить в заголовке readonly, а в категории расширить до readwrite
2. Заголовочные файлы перенести в *.m (railsware.com/...our-objective-c-projects, а объявить, что класс существует с помощью @class
3. Реогранизовать структуру проекта (файл «Anima_-_05_-_The_Waning_Moon.mp3» находится в двух местах)
4. Почитать, как лучше объявлять синглтон (stackoverflow.com/a/7569010/3717631, а потом прочитать почему лучше его не использовать (www.objc.io/issue-13/singletons.html)
5. Избегать магических констант в коде и выносить их, например, в статические переменные с осмысленными именами

Спасибо за ваше потраченное время!

1) 4 — реально классные статьи. Нужно будет попробовать метод injected reference.
2) 5, 1 — will do

Вопрос по-поводу Forward reference:
(link to repo: github.com/terancet/RussianDzen

Когда я выношу заголовочные файлы в .m, то возникает ошибка в AppDelegate:
“No known class method for selector ’sharedInstance’”.
Ругается на вот этот кусок кода:
— (void)applicationWillResignActive:(UIApplication *)application
{
[[Player sharedInstance] stopPlaying];
}
Хотя в синглетоне этот метод присутствует.
Как мне ее пофиксить?

Вы, видимо, не совсем правильно поняли лешину статью
Вот такое делать не надо: github.com/...RussianDzen/AppDelegate.h

Вместо того, чтобы удалить все из хедера, вам надо было просто
AppDelegate.h
- #import "Player.h"
+ @class Player
AppDelegate.m
+ #import "Player.h"
А то, что вы сделали просто вызовет ошибку в main.m при попытке получить [AppDelegate class]

Підписатись на коментарі