Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Принципы и практики разработки ПО / Principles and practices of software development

30 views

Published on

Lecture about software development practices and principles.

This is the first talk I gave at 2GIS internal meetup.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Принципы и практики разработки ПО / Principles and practices of software development

  1. 1. Принципы и практики разработки ПО UML SOLID SRP Single Responsibility Principle OCP Open Close Principle LSP Liskov Substitution Principle ISP Interface Segregation Principle DIP Dependency Injection Principle Encapsulation Inheritance Polymorphism AbstractionG.R.A.S.P. Inversion of Control
  2. 2. Motivation
  3. 3. { }
  4. 4. { }
  5. 5. { }
  6. 6. { }
  7. 7. { } { } { } { }
  8. 8. { } { } { } { }
  9. 9. { } { } ?
  10. 10. Inversion of Control (IoC)
  11. 11. Inversion of Control (IoC) { }
  12. 12. Inversion of Control (IoC) def download_clicks(date_from, date_to): downloader = DiggerDownloader("https://digger.2gis.ru", "user", "pass") result = downloader.download(date_from, date_to) return make_clicks(result) def main(): clicks = download_clicks("01.01.2001", "01.03.2001") do_something(clicks)
  13. 13. Inversion of Control def download_clicks(date_from, date_to, downloader): result = downloader.download(date_from, date_to) return make_clicks(result) def main(): downloader = DiggerDownloader("https://digger.2gis.ru", "user", "pass") clicks = download_clicks("01.01.2001", "01.03.2001", downloader) do_something(clicks)
  14. 14. Inversion of Control def download_clicks(date_from, date_to, downloader): result = downloader.download(date_from, date_to) return make_clicks(result) def main(): downloader = DiggerDownloader("https://digger.2gis.ru", "user", "pass") clicks = download_clicks("01.01.2001", "01.03.2001", downloader) do_something(clicks) def test_download_clicks(): test_downloader = DiggerDownloader("https://test_digger.local", "user", "pass") clicks = download_clicks("01.01.2001", "01.03.2001", test_downloader) assert(len(clicks) > 0)
  15. 15. Inversion of Control class DiggerDownloader: def download(self, date_from, date_to): ... class DiggerDonwloaderMock: def download(self, date_from, date_to): return [("branch", 1, 1020), ("street", 2, 4)] def test_download_clicks(): test_downloader = DiggerDownloaderMock() clicks = download_clicks("01.01.2001", "01.03.2001", test_downloader) assert(len(clicks) > 0)
  16. 16. SOLID principles
  17. 17. SOLID principles S SRP O OCP L LSP I ISP D DIP Single Responsibility Principle Open-Close Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
  18. 18. Single Responsibility Principle def download_clicks(date_from, date_to): with Session() as session: projects = session.get("http://search.2gis.one/projects") with open("config.json") as cfg: config = json.load(cfg) downloader = DiggerDownloader("https://digger.2gis.ru", "user", "pass") raw_clicks = downloader.download(date_from, date_to) result_clicks = {} for project_id, clicks in raw_clicks.items(): for object_id, count in clicks.items(): if object_id in result_clicks: result_clicks[object_id] += config['factor'] * count else: result_clicks[object_id] = config['factor'] * count return (result_clicks, projects)
  19. 19. Single Responsibility Principle def download_clicks(date_from, date_to): with Session() as session: projects = session.get("http://search.2gis.one/projects") with open("config.json") as cfg: config = json.load(cfg) downloader = DiggerDownloader("https://digger.2gis.ru", "user", "pass") raw_clicks = downloader.download(date_from, date_to) result_clicks = {} for project_id, clicks in raw_clicks.items(): for object_id, count in clicks.items(): if object_id in result_clicks: result_clicks[object_id] += config['factor'] * count else: result_clicks[object_id] = config['factor'] * count return (result_clicks, projects)
  20. 20. Single Responsibility Principle def download_clicks(date_from, date_to, downloader, config_path): raw_clicks = downloader.download(date_from, date_to) with open(config_path) as cfg: config = json.load(cfg) return make_clicks(raw_clicks, config['factor']) def make_clicks(raw_clicks, factor): result_clicks = {} for project_id, clicks in raw_clicks.items(): for object_id, count in clicks.items(): if object_id in result_clicks: result_clicks[object_id] += config['factor'] * count else: result_clicks[object_id] = config['factor'] * count return result_clicks
  21. 21. Dependency Inversion Principle def download_clicks(date_from, date_to, downloader, config_path): raw_clicks = downloader.download(date_from, date_to) with open(config_path) as cfg: config = json.load(cfg) return make_clicks(raw_clicks, config['factor']) class DiggerDownloader: def download(self, date_from, date_to): ... def main(): downloader = DiggerDownloader("https://digger.2gis.ru", "user", "pass") clicks = download_clicks("01.01.2001", "01.03.2001", downloader, "config.json") do_something(clicks)
  22. 22. Interface Segregation Principle class DiggerDownloader: def file_download(self, link, destination): pass def async_download_by_sql(self, params): pass def download_by_sql(self, sql, date_from, date_to, out_file): pass def task_add(self, sql, date_from, date_to): pass def task_wait(self, task_id): pass def task_get(self, task_id): pass
  23. 23. Interface Segregation Principle class DiggerDownloader: def file_download(self, link, destination): pass def async_download_by_sql(self, params): pass def download_by_sql(self, sql, date_from, date_to, out_file): pass def task_add(self, sql, date_from, date_to): pass def task_wait(self, task_id): pass def task_get(self, task_id): pass
  24. 24. Interface Segregation Principle class DiggerDownloader: def submit_download(self, task_definition: TaskDefinition) -> Task: pass def download(self, task_definition: TaskDefinition) -> Result: pass
  25. 25. Interface Segregation Principle class DiggerDownloader: def submit_download(self, task_definition: TaskDefinition) -> Task: pass def download(self, task_definition: TaskDefinition) -> Result: pass class Task: def wait(self, timeout): pass def status(self) -> Status: pass def result(self) -> Result: pass
  26. 26. SOLID principles S SRP O OCP L LSP I ISP D DIP Single Responsibility Principle Open-Close Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
  27. 27. Testing def download_clicks(date_from, date_to, downloader, config_path): raw_clicks = downloader.download(date_from, date_to) with open(config_path) as cfg: config = json.load(cfg) return make_clicks(raw_clicks, config['factor'])
  28. 28. Testing def download_clicks(date_from, date_to, downloader, config_path): raw_clicks = downloader.download(date_from, date_to) with open(config_path) as cfg: config = json.load(cfg) return make_clicks(raw_clicks, config['factor']) def test_download_clicks(): test_downloader = DiggerDownloaderMock() clicks = download_clicks("01.01.2001", "01.03.2001", test_downloader, "config.json") assert(len(clicks) > 0)
  29. 29. Testing def make_clicks(raw_clicks, factor): result_clicks = {} for project_id, clicks in raw_clicks.items(): for object_id, count in clicks.items(): if object_id in result_clicks: result_clicks[object_id] += config['factor'] * count else: result_clicks[object_id] = config['factor'] * count return result_clicks def test_make_clicks_no_data(): clicks = make_clicks({}, 1) assert(len(clicks) == 0)
  30. 30. The end

×