Архив автора: admin

Ажурный узор БАНТИКИ или БАБОЧКИ. Вязание спицами # 565

Видеоурок как вязать Ажурный узор БАНТИКИ или БАБОЧКИ. Вязание спицами.


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

Рапорт узора 12 петель+2 для симметрии +2 кромочные. Рисунок повторять с 1 по 10 ряд. На схеме показаны лицевые и изнаночные ряды, но изнаночные петли показаны так, как они выглядят с лицевой стороны. Поэтому в изнаночных рядах вяжите узор по рисунку, накиды вязать изнаночными.
светлана тим
Ажурный узор БАНТИКИ или БАБОЧКИ. Вязание спицами.

Схема Ажурный узор БАНТИКИ или БАБОЧКИ. 

Видео на моем канале ютуб Svetlana Tim


Автор: Svetlana Tim
Дата публикации: 2017-08-29T14:41:00.001-07:00

Ошибка Google привела к отключению интернета в Японии

Ошибка Google привела к отключению интернета в Японии

В прошлую пятницу, 25 августа 2017 года, интернет в Японии работал со значительными перебоями с 12:22 до 13:01 по местному времени. Виной тому стала ошибка сотрудников Google.

Проблема заключалась в проколе динамический маршрутизации BGP и ошибке в его использовании. На текущий момент BGP является основным протоколом динамической маршрутизации в интернете. Он предназначен для обмена информацией о достижимости подсетей между так называемыми автономными системами (АС, англ. AS — autonomous system), то есть группами маршрутизаторов под единым техническим и административным управлением.

ТЫ НЕ ВЕЧЕН

Страшноватенько звучит, правда?

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

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

А тут Гэри Вайнерчук со своей мотивацией: «Ты не вечен». И все, отступать некуда, перед тобой вечность, в которой тебя нет, и большой вопросительный знак посреди вечности (попробуйте себе представить эту картинку). И в этом вопросительном знаке очень много неудобных вопросов: Как жил? Чего достиг? Кому помог? Шел вперед или прятал голову в песок? Какими словами тебя вспоминают? Да и вспоминают ли?

Есть такое упражнение: попробуйте написать эпитафию о себе. Тоже дело не из приятных, но как просветляет…

Жизнь идет, прямо сейчас. А мы все ждем: окончания института, повышения по службе, когда дети вырастут – вот уж тогда начнется настоящая жизнь! Не обольщайтесь, не начнется.

Кто там мечтает попасть в будущее? Да ладно, попасть в настоящее – вот задача!

Kotlin. Часть 1. Введение

Очередной рабочий день позади и когда, как ни во вторник, лучше начать цикл статей по Kotlin. В серии следующих постов я хочу поделиться с вами опытом взаимодействия с этим языком, источниками знаний, интересными видео и, конечно, горечью от некоторых особенностей Kotlin.

Kotlin

Логотип Kotlin, куда же без него

Я хотел бы сэкономить ваше время, по этому не буду разбавлять этот текст цитатами из википедии, а дам только конкретику из своего опыта.

Kotlin — это очередной язык программирования со статической типизацией, который работает на той же виртуальной машине, что и Java. Делали его с 2010 года и не так давно он релизнулся с версией 1.0 (текущая 1.1). Совсем недавно Kotlin вошёл в топ 50 упоминаемых языков по версии индекса Tiobe (ссылка будет в конце).

Куда движется Kotlin?

Честно говоря, не понятно. Ребята, можно сказать, откусили большую часть рынка мобильной android разработки, теперь компилируются в javascript, Spring Framework уже наладили совместимость на бэкэнде, а в данный момент, параллельно с предыдущими активностями, пыхтит проект «Kotlin Native» (это LLVM бэкэнд, об этом в другой раз), который будет компилироваться под конкретную платформу и работать без виртуальной машины. Это напоминает наступление по всем фронтам (и бэкам).

Совместимость

Котлин на 100% совместим с Java. Что это означает? Вы можете взять свой Java проект и разбавить его качественным, концентрированно полезным кодом или наоборот — взять свой проект на Kotlin и написать туда немножко Java (ну как бы поностальгировать). Это одна из причин его большой популярности среди Android разработчиков. Применение первого вида совместимости понятно, вы можете использовать библиотеки типа guava или apache commons. А вот зачем нужно использование Kotlin из Java? Самое очевидное, что приходит на ум это постепенное переписывание старого кода на новый и, конечно, вы можете написать свою библиотеку на Kotlin скомпилировать её для совместимости, например, с Java 6 и использовать в вашем коде. Стоит сразу отметить, что максимальное количество преимуществ вы получаете, когда используете Kotlin вместо написания кода на Java 6.

Nullability

Разработчиков Kotlin охватила аллергия на NullPointerException и они, если и не избавились от NPE окончательно, то точно хорошо постарались, чтобы минимизировать их. Представьте, был у вас String и в нем могло лежать что угодно и строка, и null. Глядя на это JetBrains (да да, разработчики вашей любимой среды разработки еще и языки умеют делать), покачав головой добавили аппендикс вида «?» для типов переменных в которых может храниться null. Итого, в арсенале Kotlin разработчика кроме String появился String?. То же самое с остальными типами.

В Kotlin, по моим оценкам, брата NPE — KotlinNullPointerException (хитро не правда ли?) в 95% случаев можно встретить на стыке совместимости двух языков. Дело в том, что Java не знает ничего ни о каких String?, Int? и MyClass? по этому появляется специальный «платформенный тип». Вы не можете объявить переменную с этим типом сами, но выглядит он так «String!». Мне не хватает еще String% и String#, а вам?

Выведение типов

Пожалуй, лучшая фича Котлина это выведение типов (type inference). Давайте сравним:

Java 6

Map someMap = new HashMap();

Java 7, 8

Map someMap = new HashMap<>();

Kotlin

val someMap = HashMap()

Моё лицо, когда код стал короче на пару символов

В Котлине есть два ключевых слова без которых не обходится декларация ни одной переменной, это val и var. Наличие типа не обязательно, если сразу следует его декларация. Val и var означают immutable или mutable переменная соответственно. Т.е. на уровне компилятора у вас есть гарантии, что если вы написали val abc = «ok» в начале метода, то к концу метода никто не мог поменять это значение (никто никогда не использует final для переменных в Java, только зануды и разработчики библиотек).

Умное приведение типов

Приятная фишка Котлина — это «умное» приведение типов. Пример ниже:


val a: String? = "abc"
if(a != null) {
println(a.toLowerCase()) // если убрать if - код не скомпилируется
}

Компилятор «по умному» приводит String? к String и это снимает 85% оверхеда привносимого с Nullability.

Пара моментов, которых нас лишили

Здесь, естественно, не всё, а то, вы бы уснули от скуки.

Элвис бы в гробу перевернулся

Разработчики Kotlin дали нам замечательный Elvis оператор, который выглядит вот так ?: (поверните голову на -90 градусо

Kotlin. Часть 2. Незнакомые конструкции

Вот и наступил тот момент, когда вы познакомитесь с незнакомыми конструкциями в Kotlin. Эта статья является логическим продолжением Kotlin. Часть 1. Введение и её задача познакомить вас с конструкциями языка, которые могут быть крайне не привычны Java программисту. Нужно отметить, что если вы работали, например, с Groovy, то какие-то моменты вам могут быть до боли знакомы, но мы их всё равно рассмотрим. Те вещи, которые мы рассмотрели в предыдущей статье, затрагивать не будем. Если вы не прочитали предыдущую статью, рекомендую, для начала, прочитать её.

Современное лого Котлина

Для любителей проверить код

Чтобы создать простой проект на Kotlin — вам понадобится Intellij Idea Community Edition 2017 года. Скачать можно здесь. Если вы хотите полный туториал по хеллоу ворлду, то его можете прочитать и здесь, но я расскажу кратко как создать Kotlin проект с использованием системы сборки Gradle через Intellij Idea.

File -> New -> Project… -> Gradle -> Выбрать Kotlin (Java) и указать Project SDK, если не определен -> Next -> groupId и artifactId в данном случае не имеют значения, любые -> Next -> Ставим галку около Create directories… -> Next -> задаем нужный project name -> Finish

Готово! В папке src/main/kotlin вы можете писать на Kotlin.

First-class функции

В первую очередь то, что бросается в глаза это функции, которые можно писать вне классов. Типичный Hello World проект выглядит так:

fun main(args: Array) {
println("Hello World")
}

Это весь код, который нужно написать. Метод запускается без какого либо класса.

Нет ключевого слова new

Здесь всё просто, если вы хотите создать объект, вы не используете new, а просто вызываете конструктор, например:

val set = HashSet()

Классы Any, Array

В Котлине вы можете встретить несколько, а может быть и много, не знакомых классов. Краткое описание парочки таких ниже:

  • Any — местный аналог Object из которого вырезали кучу методов, например wait и notifyAll. Вы можете использовать Object, при глубокой необходимости, но часто этой проблемы нет.
  • Array — специальный класс, для работы с массивами. new MyClass[5] — конструкции в Котлине нет.

Mutable и Immutable коллекции

Вероятно, что вы помните из прошлой статьи, что переменные могут быть mutable и immutable благодаря var или val модификатору. Однако, если переменная является коллекцией, то на этот случай тоже есть свой хак. Интерфейсы List, Set, Map (Queue там нет, видимо за отсутствием смысла в неизменяемых очередях, почти как на почте) из пакета kotlin.collections — immutable, т.е. в них нет методов, которые могут изменить коллекцию, например, add для списка или put для мапы. Если вы хотите изменяемую коллекцию, то можете использовать MutableSet, MutableMap или MutableList. Таким образом вы можете декларировать можно ли менять коллекцию, которая возвращается из метода, еще на этапе компиляции, а не бросать exception во время выполнения.

Data класс

В Котлине, есть специальный модификатор, благодаря которому компилятором генерируются методы equals, hashcode, toString, copy и componentN.

data class User(val name: String)

Классы по умолчанию public final

В первую очередь, если вы джавист, создав новый класс вы привыкли видеть «public class …», здесь этого нет. Все классы по умолчанию public и final. Для того чтобы наследоваться от класса, вам нужно явно прописать модификатор open или abstract (в этом случае open подразумевается и не требуется).

Void -> Unit

Когда ваш метод не возвращает значение в Java вы пишите void в декларации метода, в Kotlin вы не пишите ничего, но в голове держите, что возвращается Unit. Это эдакая альтернатива.

Класс Nothing

Этот класс не имеет инстансов и его объявление в декларации метода как возвращаемого типа означает, что метод всегда бросает exception.

Операторы

Появился модификатор operator благодаря которому, вы можете делать собственные реализации для +, — и так далее.

Лямбды

Объявление самого простого варианта лямбды выглядит следующим образом:

() -> Unit

Здесь я привожу это для того, чтобы вы понимали с чем столкнулись, а больше подробностей о работе с лямбдами будет в последней статье серии о Kotlin.

Что я специально пропустил

Следующие вопросы я специально оставил для вашего изучения:

  • Sealed class;
  • как метод comp
    onentN улучшает читаемость кода;
  • Generics — это очень специфичная тема и для неё нужно отдельную статью;
  • модификатор infix и lambda with receiver будут рассмотрены в последней статье цикла;
  • местная альтернатива Stream API в Java — будет рассмотрена в следующей статье;

И, обязательно, я что-то пропустил не специально.

Заключение

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

Автор: Roman Brovko

Kotlin. Часть 3. Мигрируем из Java

Ранее вышло две статьи по языку Kotlin. В первой статье мы с вами познакомились с языком, а во второй рассмотрели популярные конструкции, которые могут быть не очевидны для типового Java разработчика.

Цели миграции

Прежде чем внедрять Kotlin в ваш проект давайте определимся каким целям вы следуете. Естественно вы хотите улучшить качество кода, ускорить написание и поддержку части или всей системы. Прежде всего, следует определить о каких масштабах идет речь:

  1. Вас интересуют только тесты.
  2. Вас интересует только новая функциональность или часть старого кода.
  3. Вас интересует полная замена старого кода и дальнейшая разработка.

Чем ниже позиция, тем больше масштаб трагедии.

Если вас интересует пункт 1, то данная статья вам не нужна, для вас будет 4 и 5 часть цикла о Kotlin.

Если вас интересует второй пункт, то нужно понимать, что смесь Java и Kotlin в определенных пропорциях в одном проекте может затормозить вашу работу. Но это при условии сильно смешанного Java и Kotlin кода внутри одного проекта. Об этом ниже.

Третий пункт хорош тем, что у вас не будет проблем с долгой компиляцией, как во втором случае. Однако, это путь самый долгий, но к счастью у нас есть средства автоматизации.

Картина: Котлин захватывает умы мобильных разработчиков

Java + Kotlin

Давайте разберемся как же совместно работают Java и Kotlin с технической стороны. В чем мы уверены? В виртуальной машине! Есть байт-код, который будет исполняться на виртуальной машине Java. Байт-код мы получаем в результате компиляции Java и Kotlin. На итоговой машине может стоять любая версия JVM, а нам подойдет 6, 7 или 8, т.к. Kotlin может быть скомпилирован под одну из них с незначительными ограничениями. Как вы, возможно, знаете, файлы с расширением .java, которые содержат исходный код, компилируются с помощью javac в файлы .class, которые содержат байт-код. Аналогично в случае Kotlin. Файлы с исходным кодом имеют расширение .kt, а файлы с байт-кодом также .class. Компиляция происходит с помощью компилятора kotlinc. На картинке ниже изображен упрощенный процесс сборки приложения с Kotlin.

Упрощенный процесс сборки приложения

Как видно выше приложение с Kotlin требует Kotlin Runtime библиотеки. Благодаря ним в приложении становятся доступными стандартные Kotlin классы и расширения.

Полная совместимость означает, что вы можете не только использовать классы Java, но и наследоваться от них, реализовывать интерфейсы, применять Java аннотации в своем Kotlin коде и т.д. Более того, из Java можно вызывать Kotlin код в естественном виде, никаких спец. хаков, ничего лишнего.

На случай, более привычного использования Kotlin библиотек в Java, есть специальные средства для того, чтобы минимизировать отличия Kotlin от Java после сборки. Например, first-class функции на самом деле оборачиваются в сгенерированные классы, но названия этих классов менее звучные, чем, например, StringUtils. Для того, чтобы из Java кода имена сгенерированных Kotlin классов-оберток были привычнее, вы можете использовать конструкцию

@file:JvmName("SomeUtils")

fun someFunc(param: String?) {}

Такой код в Java будет выглядеть как вызов

SomeUtils.someFunc("abc"); 

Компилятор Kotlin справляется и в случае множественных зависимостей в коде между языками, а среда разработки Intellij Idea поддерживает автодополнения и другую функциональность не смотря на смешанный код.

Теперь у вас есть представление о том как это работает. Важно отметить, что т.к. компилятор, который обрабатывает связанный код не идеален, как и любой процессинг в такой ситуации, то в проектах в которых и Java, и Kotlin присутствуют в большом объеме может замедлиться разработка. На собственном примере я ощутил как долго среда разработки выполняет автодополнение. Трудно точно локализовать проблему, но она общеизвестна и разработчики языка активно с ней борются.

Инструменты миграции

Вместе с языком Kotlin в цикл разработки входит конвертер из Java в Kotlin. Сразу обратите внимание, что обратной конвертации нет. Хорошо, если у вас есть система контроля версий, например, Git, и вы сможете отк
атить изменения, если они вас не устроят. Конвертировать можно из меню Code -> Convert Java File to Kotlin File или используйте shortcut Сtrl + Alt + Shift + K.

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

Просмотр байт-кода

В плагин для Kotlin входит функциональность просмотра получающегося байт кода. Для того чтобы его увидеть достаточно в меню Tools -> Kotlin выбрать Show Kotlin Byte code.

Заглянем за кулисы

Давайте посмотрим на особенности байт-кода Kotlin. Там мы можем найти кое что интересное для понимания принципов языка.

Такая замечательная вещь как контроль Nullability привносит с собой не значительный оверхед в виде явной проверки на null. Для примера я приведу пустой метод, который ничего не делает, но требует значение параметра не равный null (напомню, что в случае nullable параметра в Kotlin используется String?).

fun someFunc(param: String) {} 

Для этого метода, кроме RETURN команды, в байт-коде мы увидим явную проверку на null:

INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V

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

fun someFunc(param: String?) {}

из байт кода, естественно, исчезает проверка, но всегда генерируется аннотация Nullable или NotNull (это помогает среде разработки подсвечивать опасное использование переменных, которые могут быть null)

  @Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0

Особенности конвертации

Конвертер не стоит на месте и силами разработчиков языка исправляются всё больше ошибок. Наиболее мажорные из них исправлены к версии 1.1. Тем не менее, конвертированный код не идеален и ниже рассмотрим конвертацию лямбд из Java в Kotlin, а также Stream Api.

Отличие лямбд в Kotlin и Java

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

Один из приятных моментов, который Kotlin привносит в возможности языка — это inline функции. Проще говоря — компилятор способен встроить код того или иного метода в место вызова и, как следствие, это иногда влечет за собой ускорение, при увеличение размера байт-кода.

Например, код метода main

fun main(args: Array) {
invokeLambda {
println("Hello world")
}
}

inline fun invokeLambda(lambda: () -> Unit) {
lambda()
}

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

fun main(args: Array) {
println("Hello world")
}

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

При нежелании, чтобы ваша лямбда была «заинлайнена» используйте ключевое слово noinline для параметра inline функции.

Рассмотрим результат конвертации лямбды. В Java, обычно, для типичных лямбд используются такие функциональные интерфейсы как Runnable, Supplier, Function и т.д. В Kotlin же, как вы уже знаете, тип лямбды декларируется как (ParamsTypes) -> ReturnType. Изначально мы имеем следующий код:

public class Example {
public static void main(String[] args) {
invokeLambda(() -> {
System.out.println("Hello world");
});
}
private static void invokeLambda(Runnable lambda) {
lambda.run();
}
}

В результате конвертации мы получаем Kotlin код:

object Example {
@JvmStatic fun main(args: Array) {
invokeLambda { println("Hello world") }
}
private fun invokeLambda(lambda: Runnable) {
lambda.run()
}
}

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

Для того чтобы метод main из Java был представлен как статический (в Kotlin нет статических методов, для этих целей обычно служит companion object) используется аннотация @JvmStatic.

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

fun main(args: Array) = invokeLambda { println("Hello world") }

private fun invokeLambda(lambda: () -> Unit) = lambda()

В версии Kotlin 1.1 всё конвертируется отлично, хотя в прошлых версиях была проблема с конвертацией лямбд.

Stream Api

Как вы знаете, с появлением Java 8 в арсенале разработчика появился мощная возможность. Имя ей Stream Api. Задача, которая решается с его пом
ощью — это обработка коллекции данных в функциональном стиле. При этом код в Java выглядит компактным и хорошо структурированным. В Stream Api есть терминальные операции — это завершающие операции, при достижении которых начинается обработка описанного стрима (forEach, collect, sum и т.д.). Важный момент, стримы в Java исключительно lazy, т.е. выполняются только при достижении терминальной операции, а если её нет, то стрим просто ничего не сделает.

В Kotlin, есть аналог Stream Api, но в отличии от Java есть еще и не lazy обработка. Она доступна прямо на уровне коллекции, например

val incrementedCollection = someIntCollection.map { it + 1 }

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

Обратите внимание, что когда мы используем функцию map для коллекции, то это inline функция, т.е. фактически код будет встроен в место вызова, однако это не верно для функции map у последовательности.

Итак, давайте конвертируем Java stream в Kotlin. Пусть у нас есть исходный код, который должен собирать фразу «hello world !» на Java вот таким изощренным способом.

List words = Arrays.asList("Hello", "my", "world", "world", "!");
String resultString = words.stream()
.filter((word) -> !Objects.equals("my", word))
.map(String::toLowerCase)
.distinct()
.collect(Collectors.joining(" "));
System.out.println(resultString);

Воспользуемся конвертером

Бэм! И мы получили не компилируемый код. Как я писал, конвертер не идеален.

val words = Arrays.asList("Hello", "my", "world", "world", "!")
val resultString = words.stream()
.filter { word -> "my" != word }
.map(Function { it.toLowerCase() })
.distinct()
.collect(Collectors.joining(" "))
println(resultString)

Для начала заставим его компилироваться. Для этого подкорректируем его и получим уже компилируемый код

val words = Arrays.asList("Hello", "my", "world", "world", "!")
val resultString = words.stream()
.filter { word -> "my" != word }
.map { it.toLowerCase() }
.distinct()
.collect(Collectors.joining(" "))
println(resultString)

В принципе, задача решается уже верно, но давайте перепишем на нативное использование Kotlin без привязки к Java. Ради красоты и читаемости.

    val words = listOf("Hello", "my", "world", "world", "!")
val resultString = words.asSequence()
.filterNot { it == "my" }
.map(String::toLowerCase)
.distinct()
.joinToString(separator = " ")
println(resultString)

Готово! Понимаю, что использование filterNot, конечно, на любителя, но в целом мы имеем отличный, читаемый, компилируемый ленивый поцессинг коллекции. А если убрать asSequence, то процессинг перестанет быть ленивым. Оператор «==» в Kotlin это equals в Java, т.е. в Kotlin строки можно всегда сравнивать через «==».

Модификатор internal

Наконец, в Kotlin есть модификатор internal использование его обозначает, что метод/класс/поле доступно к использованию только внутри модуля (jar-ника). Если вы использовали для класса A этот модификатор, запаковали его и подключили как зависимость, то этого класса в зависимом проекте вы не найдете. Но как вы понимаете в Java нет ничего подобного, а всё реализуется на виртуальной Java машине. Решение оказалось не сложным. При компиляции internal компоненты языка проходят своего рода обфускацию, т.е. они переименовываются страшным образом и использовать такие поля/методы/классы из Java кода не очень хочется.

Заключение

В этой статье мы рассмотрели как работают вместе Java и Kotlin. Какие проблемы могут быть и как они решаются. Я постарался раскрыть эту тему наиболее полно, но если у вас остались какие-либо вопросы, то вы можете их задать.

Автор: Roman Brovko