Pull to refresh
@Scfread⁠-⁠only

User

Send message

У меня такой же опыт. Начинал свою карьеру с JSF+Hibernate+Spring, не зная ни джаваскрипта, ни толком SQL, ни умея проектировать и структурировать код. И, соответственно, тратил огромное количество времени, пытаясь понять, почему оно работает не так.

Код для "склеивания" существующих библиотек, как правило, невелик по объему и сильного погружения не требует, отдельные библиотеки хорошо документированы и просты в понимании. Сбор библиотек в приложение — да, инвестиция, но с хорошим возвратом.

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


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

Фреймворк должен помочь вам:
[список требований]

Всё это делается спецализированными библиотеками, которые комбинируются в приложение.


По моему опыту, есть только 3 причины использовать фреймворки:


  • Недоступность квалифицированных разработчиков
  • Низкие требования к качеству приложения (размер, быстродействие, нестандартные фичи)
  • Прототипирование

Latency какой получился? Смотрел на этот стек пару лет назад — у лямбды высокое и нестабильное время ответа, S3 тоже работает существенно медленнее, чем хостинг на EC2 + nginx

Есть только три причины использовать Linux в 2020 году:


  • чтобы не использовать Windows (здесь длинный список причин не использовать Windows)
  • вы программируете для Linux
  • вы не любите мак

Эта проблема решается клавишей PageDown

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


Но у пролога есть большая проблема — по исходному коду крайне сложно сказать, как именно он будет работать. Из чего следует три проблемы побольше:


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

Это известная проблема еще со времен глянцевых журналов, когда девочки задавали себе недостижимые планки стандартов красоты по фотошопленным фоткам моделей.


Я думаю, что можно законодательно обязать ставить специальную пиктограмму на все обработанные/ретушированные фотографии.

Это же cats, и всё делается в одну строчку. Хотя да, для людей, не умеющих свободно обращаться с котами и эффектами, библиотека может быть полезна.

Не совсем. Хранимки становятся нужны, когда у тебя в джаве — класс Order, а в базе — десяток нормализованных таблиц. При этом по этой же базе хотят гонять аналитические запросы или ETL, а к базе прилагается собственный DBA.


Лучше, конечно, не увлекаться нормализацией и держать схему БД как можно проще, но получается не всегда, как по техническим, так и по организационным причинам.

Забыли еще один плюс ХП: PL/SQL сконструирован для удобной работы с базой данных. Так что для сложных баз данных логику извлечения данных и, особенно, сохранения имеет смысл делать на ХП.

Нужна ли для этого библиотека?


// чтение чего угодно
val reader: Request => F[Option[Response]]
// выброс нужной ошибки, если данных нет
val reader1: Request => F[Response] = req => reader(req).flatMap {
  case Some(v) => v.pure[F]
  case None => xxxxx.raiseError[F, ....]
}
// батчинг
requests.traverse(reader1)
// параллельное исполнение
requests.parTraverse(reader1)
// дедупликация
requests.distinct.traverse(reader1)
// кеширование
val cache: (Request => F[Response]) => (Request => F[Response]) = ???
requests.sequence(cache(reader1))

Бедная сова. Бедный глобус.


Больше всего порадовал тезис, что облака нужны для сбора персональных данных пользователей: статистика в мобильных приложениях и видеозвонки в слаке (или авторы теста не слышали про peer-to-peer)

Ubuntu, Radeon. Работать нормально, играть не очень. Часть игр под линукс выпускается только под nvidia, аппаратное ускорение видео не работает, под wine постоянно вылазят косяки драйвера.

Ну зачем сразу в крайности. Инструменты очень важны. Люди и взаимодействие тоже очень важны. Солдат без правильной морали и командования не опаснее гопника, какое оружие ему ни дай.


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

человеку покормить кошку, воспользовавшись кормушкой

Некорректная формулировка. Это два разных действия — насыпать корм из человека в кормушку, пересыпать корм из кормушки в кошку.

Да, Мартин гораздо более публицист, чем программист, его FitNesse — достаточно глючная вещь и не со всеми его рецептами можно согласиться. Но CleanCode подробно отвечает на вопросы новичков о том, чем отличается хороший код от плохого, и однозначно повлияла на моё мировоззрение в лучшую сторону.


Поэтому рекомендовал и буду рекомендовать.

В вашем коде (как и в моем) нет повторно используемых компонентов, помимо, возможно, функции fizzBuz/row


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


Ваш вариант fizzBuz нарушает I в SOLID — передаваемые тайпклассы избыточны и если клиент захочет использовать эту функцию со сторонним типом, у него будут проблемы. С другой стороны, эти тайпклассы не делают бизнес-логику более понятной — идеально написанный код по требованиям должен совпадать с требованиями построчно, вы же используете "особенность" — что FizzBuzz состоит из Fizz и Buzz

Я бы не стал так делать, очень много букв, очень хрупкий код. Вот мой вариант, на Tagless Final:


import simulacrum._
import scala.language.implicitConversions

// define operations on A required by FizzBuzz business logic
@typeclass
trait FizzBuzzNumber[A] {
  // return true if a is divisible by v
  def divisibleBy(a: A, v: Int): Boolean

  // format A according to FizzBuzz requirements
  def show(a: A): String
}
// import simulacrum-generated ops on A
import FizzBuzzNumber.ops._

// totally abstract business logic
def row[A: FizzBuzzNumber](a: A): String = {
  val by3 = a.divisibleBy(3)
  val by5 = a.divisibleBy(5)

  if (by3 && by5) "FizzBuzz" 
    else if (by3) "Fizz"
    else if (by5) "Buzz"
    else a.show
}

//
// implement FizzBuzz on ints
//
implicit val intInstance: FizzBuzzNumber[Int] = new FizzBuzzNumber[Int] {
  def divisibleBy(a: Int, v: Int): Boolean = a % v == 0
  def show(a: Int): String = a.toString
}

// lazy rows, to do not allocate memory for all 100 rows at once
val rows: Iterable[String] = (1 to 100).view.map(v => row(v))

rows.foreach(println)

Запускаемый вариант: https://scastie.scala-lang.org/PlKt79BOQ6afkgHveSjyIA

Information

Rating
Does not participate
Registered
Activity