58
Мой сосед Легаси Федоров Сергей, Evil Martians

«Мой сосед Легаси», Сергей Федоров, Evil Martians

Embed Size (px)

Citation preview

Page 1: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Мой соседЛегаси

Федоров Сергей, Evil Martians

Page 2: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Проект AmplifrПроект AmplifrПроект Amplifr

Проект Amplifr

—  Музыкальная индустрия

—  4 соцсети

—  Публикации

—  Простая аналитика

Page 3: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Проект AmplifrПроект AmplifrПроект Amplifr

Проект Amplifr

—  100% SMM

—  12 соцсетей

—  Публикации

—  Аналитика

—  Рекомендации

—  Рассылки

Page 4: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Проект Amplifr

Эволюция VS Революция

Page 5: «Мой сосед Легаси», Сергей Федоров, Evil Martians

О чем доклад?

О простых и дешевых приемах,которые позволят вам и вашейкоманде эффективно работатьс легаси кодом

Page 6: «Мой сосед Легаси», Сергей Федоров, Evil Martians

ФорматированиеФорматированиеФорматирование

Форматирование

Page 7: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

Никому не нравится читать плохоотформатированный код

Page 8: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

update_activity(publication, activity)

total = activity.values.sum

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 9: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

total = activity.values.sum

update_activity(publication, activity)

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 10: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

total = activity.values.sum

update_activity(publication, activity)

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 11: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

total = activity.values.sum

update_activity(publication, activity)

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 12: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

total = activity.values.sum

update_activity(publication, activity)

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 13: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

total = activity.values.sum

update_activity(publication, activity)

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 14: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

def write_stats(publication, total, data = {})

activity = count_total_from_publication_data(publication)

total = activity.values.sum

update_activity(publication, activity)

if override_stat_date?(publication, 'created_at')

data[:date] = Time.parse(publication.data['created_at'])

end

unless dont_write_stats

if plays_total = publication.data.try(:[], 'playback_count').to_i

stat = \

Stat.record_total(

"soundcloud_plays",

{ project: publication.project, resource: publication }.merge(data),

plays_total

)

end

end

super

end

Page 15: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

Современные IDE поддерживаютфункцию автоматическогоформатирования кода

Page 16: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

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

Page 17: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

Взаимозависимые функциидолжны размещатьсяв нисходящем порядке

Page 18: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Форматирование

Единый стиль форматированияуменьшает вероятность ошибки

Источник: Robert C. Martin: Clean Code, A Handbook of Agile Software Craftsmanship

Page 19: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные именаНеправильные именаНеправильные имена

Неправильные имена

Page 20: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

Самое трудноев программировании —это придумывать имена

Page 21: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

Комментарии могут обманыватьтак же, как и неверные имена

Page 22: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

Плохое имя — как магнитдля лишней функциональности

Page 23: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

def access_token

# We store only refresh token and for each request

# just fetching new access token

api = Odnoklassniki::Client.new(

access_token: @account.token,

client_id: Settings.odnoklassniki.app_id,

client_secret: Settings.odnoklassniki.app_secret,

)

new_token = api.refresh_token!

raise Social::API::Unauthorized if new_token.blank?

api

end

Page 24: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

def access_token

# We store only refresh token and for each request

# just fetching new access token

api = Odnoklassniki::Client.new(

access_token: @account.token,

client_id: Settings.odnoklassniki.app_id,

client_secret: Settings.odnoklassniki.app_secret,

)

new_token = api.refresh_token!

raise Social::API::Unauthorized if new_token.blank?

api

end

Page 25: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

def access_token

# We store only refresh token and for each request

# just fetching new access token

api = Odnoklassniki::Client.new(

access_token: @account.token,

client_id: Settings.odnoklassniki.app_id,

client_secret: Settings.odnoklassniki.app_secret,

)

new_token = api.refresh_token!

if new_token.blank?

@account.disable!

raise Social::API::Unauthorized

end

api

end

Page 26: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Неправильные имена

def rest_client_with_refreshed_token

client = Odnoklassniki::Client.new(

access_token: @account.token,

client_id: Settings.odnoklassniki.app_id,

client_secret: Settings.odnoklassniki.app_secret,

)

refreshed_token = client.refresh_token!

raise Social::API::Unauthorized if refreshed_token.blank?

client

end

Page 27: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRYДублирование и DRYДублирование и DRY

Дублирование и DRY

Page 28: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRY

Все ли дублирование стоитустранять?

Page 29: «Мой сосед Легаси», Сергей Федоров, Evil Martians

module Social

module API

class Vkontakte

def initialize(access_token)

@access_token = access_token

end

# ...

end

end

end

module Social

module API

class Twitter

def initialize(access_token)

@access_token = access_token

end

# ...

end

end

end

Дублирование и DRY

Page 30: «Мой сосед Легаси», Сергей Федоров, Evil Martians

module Social

module API

class Base

def initialize(access_token)

@access_token = access_token

end

end

end

end

module Social

module API

class Vkontakte < Base

# ...

end

end

end

Дублирование и DRY

Page 31: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRY

module Social

module API

class Base

def initialize(access_token)

@access_token = access_token

end

def rescue_api_errors(error, args)

# ..

end

def send_notification

# ...

end

end

end

end

Page 32: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRY

Понятность кода не должна бытьценой устранения дублирования

Page 33: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRY

С дублированием кода вполнеможно жить

Page 34: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRY

Неверные абстракции устранятьсложнее, чем дублирование

Page 35: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Дублирование и DRY

Устраняя дублированиеруководствуйтесь примерамииспользования кода

Page 36: «Мой сосед Легаси», Сергей Федоров, Evil Martians

ИнтерфейсыИнтерфейсыИнтерфейсы

Интерфейсы

вместо методоввместо методоввместо методов

вместо методов

Page 37: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

Лучший код — код которого нет

Page 38: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

Копирование или расширениесуществующих методов — ложныйreuse

Page 39: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

def fetch_account_publications(opts = {})

all = api_fetch

posts = all['feeds']

entities = all['entities'].try(:[], 'media_topics') || []

return unless posts.present? || entities.present?

posts.each do |story|

publication = find_publication(story)

likes = entities.find { |it| it['ref'] == story['target_refs'].try(:[], 0) }

likes = likes['like_summary']['count'] if likes

likes ||= 0

comments = story['discussion_summary'].try(:[], 'comments_count').to_i

shares = 0

update_activity(publication, {like: likes, share: shares, comment: comments})

total = comments + likes

write_stats(publication, total) if publication.is_a?(Social::ExternalPublication)

end

end

Page 40: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

def fetch_account_publications(opts = {})

all = api_fetch

posts = all['feeds']

entities = all['entities'].try(:[], 'media_topics') || []

return unless posts.present? || entities.present?

posts.each do |story|

publication = find_publication(story)

likes = entities.find { |it| it['ref'] == story['target_refs'].try(:[], 0) }

likes = likes['like_summary']['count'] if likes

likes ||= 0

comments = story['discussion_summary'].try(:[], 'comments_count').to_i

shares = 0

update_activity(publication, {like: likes, share: shares, comment: comments})

total = comments + likes

write_stats(publication, total) if publication.is_a?(Social::ExternalPublication)

end

end

Page 41: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

def fetch_account_publications(opts = {})

all = api_fetch

posts = all['feeds']

entities = all['entities'].try(:[], 'media_topics') || []

return unless posts.present? || entities.present?

posts.each do |story|

publication = find_publication(story)

likes = entities.find { |it| it['ref'] == story['target_refs'].try(:[], 0) }

likes = likes['like_summary']['count'] if likes

likes ||= 0

comments = story['discussion_summary'].try(:[], 'comments_count').to_i

shares = 0

update_activity(publication, {like: likes, share: shares, comment: comments})

total = comments + likes

write_stats(publication, total) if publication.is_a?(Social::ExternalPublication)

end

end

Page 42: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

def get_publication_activity(story)

publication = find_publication(story)

likes = entities.find { |it| it['ref'] == story['target_refs'].try(:[], 0) }

likes = likes['like_summary']['count'] if likes

likes ||= 0

comments = story['discussion_summary'].try(:[], 'comments_count').to_i

shares = 0

{likes: likes, comments: comments, shares: shares}

end

Page 43: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

class PublicationStatistics

def likes

# ...

end

def comments

# ...

end

def shares

# ...

end

end

Page 44: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Интерфейсы вместо методов

Производите анализ имеющегосякода

Page 45: «Мой сосед Легаси», Сергей Федоров, Evil Martians

ТестыТестыТесты

Тесты

Page 46: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Тесты

Код без тестов — легаси код

Источник: Michael Feathers: Working Effectively with Legacy Code

Page 47: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Тесты

Как бы небыл понятен код —не факт, что ты ничего не сломал

Page 48: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Тесты

Критичные участки кода должныбыть покрыты тестами

Page 49: «Мой сосед Легаси», Сергей Федоров, Evil Martians
Page 50: «Мой сосед Легаси», Сергей Федоров, Evil Martians

РефакторингРефакторингРефакторинг

Рефакторинг

Page 51: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Рефакторинг

Довольно дорогой процессдля бизнеса

Page 52: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Рефакторинг

Очень сложно уложитьсяв отведенное время

Page 53: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Рефакторинг

Параллельная разработка делаетрефакторинг в разы сложнее

Page 54: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Заключение

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

Page 55: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Заключение

Теория разбитых окон — устраняямалозначительные недочеты, выне допускаете более крупных

Page 56: «Мой сосед Легаси», Сергей Федоров, Evil Martians

Заключение

Разработка через рефакторинг

Page 57: «Мой сосед Легаси», Сергей Федоров, Evil Martians

ВопросыВопросыВопросы

Вопросы

Page 58: «Мой сосед Легаси», Сергей Федоров, Evil Martians

—  Почта: [email protected]

—  Твиттер: @oni_strech

—  Слайды: strech.github.io/my-neighbor-legacy