Programcıları temel kuralları izlemeye ikna etme


20

Programcılardan çok sık takip etmelerini istemem gereken birkaç kural var. Kod yazarlar ve eğer çalışırlarsa, onlar için iş yapılır. En temel kurallar şunlar olabilir:

  • Değişikliklerin yerine getirilmesi
  • Görünüm veya Denetleyicilere Model sorunları yazmama
  • Sabit kodlamadan kaçının

Bana deneyiminden bahseder misin? Bunu nasıl yönetiyorsunuz?


2
Programmers.stackexchange.com adresine sormalısınız. Kod incelemeleri yapıyor musunuz? Crucible gibi bir kod inceleme aracınız var mı? Kapsamlı kod değerlendirmeleri yapmak ve tüm diğer çalışmalar yapılmadan önce çözülmesi gereken tüm konularda ısrar öneriyoruz .

15
Godfather'da çalışan yatağının üstünde at başını bırakmayı deneyebilirsiniz.
Gaurav

4
Yüksek voltaj ile büyük başarı elde ettim. Kilometreniz değişebilir.
Tim Post

2
@Tim: toplu gazete daha çevre dostu
Steven A. Lowe

@Steven, sanırım olurdu. Önce gazeteyi yeniden amaçlayın, sonra yeniden çevrim yapın. Sanırım yeşil gözdağı verme sanatı var.
Tim Post

Yanıtlar:


6

Tüm bilgi çalışanlarının kaliteli işler yapabilmeleri için meydan okunmaları gerekir. Kalite, üzerlerinde keyfi zaman kısıtlamaları olduğunu düşünürlerse zarar görür. Neden herkes şartnamelerin yerine getirilmesi ve son teslim tarihlerinin karşılanması konusunda endişe duyduğunda "yeterince iyi" şeyler yapmıyorsunuz?

Şikayet listeniz, yalnızca kısa vadeli hedefleri karşılamayı ödüllendiren ve yüksek kaliteye önem verme arzusu olmayan bir şirketin belirtileridir. Beş yıldızlı bir otel mi yoksa kamyon durağı mı kullanıyorsunuz?


1
Bunun kültürel bir sorun olduğuna işaret etmek için +1 ve motivasyon açısından ele alınması gerekiyor.
Alex Feinman

bu hem JeffO tarafından öne sürülen bir şirket kültürel meselesidir. ancak bazen kodlayıcıların ve geliştiricilerin kalite kodu veya ihtiyacı için hiçbir vizyonu olmadığında bu kültür aşağıdan yukarıya doğru pişirilir. Bilgisayar Bilimleri okulundayken, profesörlerinin birkaç kez başlarının kenarlarına tokat atması gerekiyordu.
robert bristow-johnson

@ robertbristow-johnson - İyi bir nokta.
JeffO

14

Temel kuralları takip edebilmek için kuralların ne olduğunu bilmeleri ve onlarla aynı fikirde olmaları gerekir.

Bununla başa çıkmanın yolu, herkesin hemfikir olabileceği bir kodlama kılavuzu belgesi oluşturmaktır . Onları zorlamaya çalışmayın, eğer yaparsanız geri tepecektir.

Ekibi bir araya getirin ve temel kurallarınızın ortak bir tanımı üzerinde çalışmaya başlayın!

Bunu tüm seslerin duyulduğu bir atölye olarak yapın. Sonsuz tartışmalardan kaçınmak için zamanlayın. Birkaç zihni bir araya getirmeye çalışıyorsunuz, bu yüzden sahneyi hepinizin saygılı olması ve açık bir zihin tutması gerektiği konusunda olumlu bir notla ayarlamak isteyebilirsiniz (kod yazma kişiseldir ...).

Ekibin eklenmesi veya netleştirilmesi gereken bir şey olduğunu hissettiğinde bu yönergeler canlı olarak değiştirilmelidir.


2
Kabul etsem de, "Onları zorlamaya çalışmayın, eğer yaparsanız geri tepecek." - Her şey söylendiğinde ve yapıldığında, birinin temel kuralları kabul edip etmediği önemsizdir. Patron kuralları yapar, onları takip eder veya başka bir iş bulur. İşveren-işçi ilişkisi geçerli olmayacak kadar özel değiliz.
Steven Evers

12

Senin rolün ne? Kod kalitesine özellikle ilgi duyan başka bir geliştiriciyseniz, muhtemelen sizi dinlemelerini sağlama yetkiniz yoktur ve belki de olması gereken / olması gereken kod standartlarını oluşturmak için bu fikirleri yönetime yükseltmelisiniz. takip etti. Eğer bir yönetici / takım lideri / mimarı iseniz ve bir otoriteye sahipseniz, bu uygulamaları kendiniz kurabilirsiniz. Bunları ayıklamak için bir standartlar belgesi ve bir kod inceleme süreci oluşturun.

Açabileceğiniz sihirli bir anahtar olmayacak; yavaş bir süreç olacak ve asla% 100 olmayacak. Zaten benim deneyimim bu oldu.


1
Katılıyorum. Bu teknik değil, politik bir konudur.

Ve herhangi bir kod standardının en azından kısmen grup tarafından üzerinde anlaşılması gerekir. StyleCop gibi araçlar çok yardımcı olur.
İş

Patronum onun "kod kalitesini" zorlamaya çalışıyor, ama sadece havalanmıyor, çünkü insanlar buna inanmıyor. güce sahip olmak her zaman cevap değildir.
IAdapter

@ 0101 Çok doğru. Güç, mesajı itmeye yardımcı olur. Mesaj, kabul edilmek ve takip edilmek için hazırlanmalıdır.
RationalGeek

7

Şimdiye kadar tüm cevapların mantıklı bir kombinasyonu olmalı. Sonunda, bir grup akıllı insandan (geliştirici) bahsederken, onlara davranışın neden önemli olduğunu göstermelisiniz ve onlara bu davranışın doğru şekilde yapılması için nasıl yatırım yapıldığı konusunda yeterince kontrol vermelisiniz . Yukarıdan gelen görevler genellikle akıllı insanlar için gevşektir, çünkü sorunun bir sorun olduğunu kabul etmedikleri takdirde, kuralı takip etmek yerine yetki etrafında çalışmak için daha fazla zaman harcayacaklardır.

İşte benim taktiklerimden birkaçı:

Taahhüt Değişiklikleri:

İlk olarak, takımın ne zaman ve ne taahhüt edeceği konusunda anlaşması gerekir. Kesinlikle önemli olan, mantıklı bir yapı kurulumudur, böylece insanlar sadece bir şeyi nereye koyacaklarını bilmedikleri için uzak durmazlar. Ve ne zaman / ne sıklıkta kontrol edileceği konusunda fikir birliği. "Yapıyı kırma" açık bir iyi kuraldır, ancak bu nasıl kontrol edilir ve kim bundan bahsedilir? Başka bir taban çizgisi ise "teslim edilmezse yapılmaz" dır.

Tanıdığım çoğu geliştirici kod IF check-in için çok mutlu:

  • Check-in işlemi kolaydır
  • Senkronizasyon işlemi kolaydır (diğer geliştiricilerin değişikliklerinde faktoring)
  • Değişiklikleri görmek ve sürümler arasında geçiş yapmak kolaydır

Son zamanlarda fark ettiğim bir şey, yeni bir CM aracına doğru ilerlediğimizde checkin'lerin daha sık ve daha az acı çekmesiydi. Ekibimiz daha önce Clearcase'i kullanan Rational Team Concert'e öncülük ediyor. Araçların reklamını yapmak istemiyorum, ancak çok sayıda küçük, hızlı birleşmeyle yeni (bana) akışlı checkin dalgası, erken ve sık sık check-in yapmayı daha cazip hale getiriyor.

Geliştiricilerin CM ağrısını ortadan kaldırmakla sorumlu olmasına izin vermek genellikle gerçekleşen checkin miktarını artırır.

Mimarlığa Bağlılık - Görünümlerde ve Kontrolörlerde Model Sorunları Yazmamak

Bunu "mimariyi doğru bir şekilde yapın" genel kümesine koyuyorum. Akran değerlendirme kim dedi katılıyorum - akran baskısı bunun için harika. Genelde insanların bu alandaki en iyi uygulamalar için ortaya çıktığını gördüğüm yollardan biri, akranlarının onlara neden başka şekilde yaptıklarını sormasıdır (o kadar doğru değil). Genellikle "neden" sorusu, insanları neden farklı bir şekilde yapmaları gerektiğini fark etme yoluna götürecektir. İnsanlar en iyi uygulama için iyi anlaşılmış bir nedene sahip olduklarında, buna uymak çok daha kolaydır.

Ayrıca, bir kişiyi bir karara bağlayan bir formalite varsa, o zaman bu alanda hata atamak daha kolay olabilir ... yani bir kişi hatalı bir tasarım alanındaki hataları düzeltmekten sorumlu ise, daha önce bir şey alma ihtiyacı yeni bir şeye geçebilirler ve heyecan verici büyük bir motivasyon kaynağı olabilir.

Hardcoding kullanmaktan kaçının

Açık kodlama standartları ve akran incelemelerinde bir kodlama standart incelemesi entegre ile başlar. Sabit kodlama, akran değerlendirme gündeminde kolayca bir onay kutusu olabilecek şeylerden biridir.

Korkarım ki takımın rolü haline geldiğini gördüğüm tek şey kuralın uygulanmasına yol açıyor. Koştuğum takımlarda, genellikle kodlarının akran değerlendirmesinden gelen yorumları düzeltene kadar birisinin devam etmesine izin vermeyiz. Ve "sabit kodlama yok" sık bir hakem yorumu yorumudur.

Genel olarak

Hemen hemen en iyi uygulamalarla, bence savaşlarını seçmelisin. Hiçbir takım kesinlikle mükemmel olmayacak. Ancak, büyük ağrı noktalarınıza göz kulak olabilir ve bunları kümeler halinde ele almaya başlayabilirsiniz. Belirli bir bireyin can sıkıcı bir tuhaflığına karşı takım için bir ağrı noktasının ne olduğunu gerçekten bilmek liderin rolü haline geldi.

Ekibiniz belirli bir en iyi uygulamayı yapmayı kaçırıyorsa, bence ilk soru "bu ne kadar zarar veriyor?" cevap "minimal" ise, muhtemelen zaman ayırmaya değmez. Bazı en iyi uygulamalar, belirli sistem türleriyle en alakalı olanıdır - genel olarak iyi olmalarına rağmen, uygulamanın sık sık meydana geldiği veya sistemin büyük bir parçası olmadığı sistemler için savaşa değmeyebilirler.

Eğer cevap "ne kadar damange?" "ALOT !!!" ise, takıma tüm bu acı ve ıstırapların en iyi uygulamalarda bu bir gevşeme noktasını sabitleyerek giderilebileceğini göstermek için bir vaka oluşturmaya başlayabilirsiniz. Çoğu insan acı ve ıstıraptan kaçınmaktan mutluluk duyar ve bu diyaloğu "bunu size söyledim çünkü" demiştim "den," bunu daha iyi olduğu için yapmaya karar verdik "şeklinde değiştirir.


Uzun yorum, ama yaklaşım harika. İnsanların bu yönergelere uymalarını sağlamak için bunun bir yarar olduğuna inanmaları gerekir. Bunun ekibiniz için nasıl çalıştığına dair bazı örnekler duymak isterim.
jmort253

En sevdiğim örnek tutarlı bir test ortamı kurulumu. Doğru Yolu uygulamak zorunda değildim. Kurulum belgesinden sorumlu bir adamım vardı. Dedim ki - "her şey sen - tutarlı kurulum sağlayan bir kurulum mekanizması yapmak için ne gerekiyorsa yapabilirsin - herkes, kurulum bozulursa size hata vermeye yetkilidir". Bir aydan kısa bir sürede sağlam bir araç ve çok kısa bir belgemiz vardı. Ve araç her masaüstüne kısa yol olarak kuruldu. Uygulamaya ihtiyacım yoktu, düzgün kurulum zaten en az direnç yoluydu. Şimdi amacımız kısayolu kaldırmak ve otomatik hale getirmek.
bethlakshmi

6

Kod incelemesi. Yalnızca hatasız iyi yazılmış bir kodu kabul edin.


3
Bu, altta yatan sorunun çözümü değildir. Bunun yerine kök neden sorununu çözebileceğiniz kod incelemeleriyle zaman kaybetmeyin.
Martin Wickman

Eğer onları tekrar tekrar iş yapmaya zorlayabilirseniz, içsel tembellikleri zaman içinde uymaya başlayacaktır.
David Thornley

Anlaşılan, insanların sadece sorumlu olması ve işlerini söylenmeden yapmaları gerekiyor. Her değişiklikten sonra kod incelemesi büyük bir zaman kaybıdır.
jmort253

5

En azından :

  • Kod çizgilerini takip etmelerini kolaylaştırın (yeniden birleştirici, StyleCop gibi araçlar) Kolaysa, benimseme olasılıkları daha yüksektir.

Bunun yanı sıra kuruluşunuza, geliştiricilere ve ekip içindeki rolünüze göre neyin işe yaradığını seçin.

  • Hata düzeltmelerini yapmalarını ve isteği düzenli olarak değiştirmelerini sağlayın
  • Programı deneyimli bir geliştiriciyle eşleştirme
  • İncelemeleri yapıcı bir şekilde kodlayın
  • Kod yönergeleri
  • Eğitime başlayın, Code Complete ve The pragmatic programcı gibi kitapları kullanın.

5

Rolüm Yönetici, ancak küçük bir ekip olarak gelişiyorum ve daha çok koç olarak yönetmeyi tercih ediyorum.

Bir kod ayrıştırıcıya bağlı sandalyedeki elektrotlar zaten işaret edildi, ancak programcılar korkmuyor gibi görünüyor. Ateş etmek iyi bir yaklaşım olarak görünmüyor, çünkü bu değerli varlıkların kaybedilmesi anlamına geliyor.

Tüm bu araçlara bir göz atacağım ve bana söylediğin diğerlerine açık kalacağım.


3
Varlıklarınız bu kadar değerliyse, bu sorunlar belki de o kadar önemli değil mi? Savaşlarını bir süre seçip seçmelisin.
JeffO

Benim sorum, arama ve değiştirmekten daha zor ama etkili olanı geliştirmeyle ilgili
Llistes Sugra

Kodlama kurallarına uymayacak insanları kovmak iyi varlıkları kaybetmek DEĞİLDİR, deadwood'dan kurtulmaktadır.
HLGEM

@HLGEM - Kurallara uymayan kişi sadece organizasyondaki herhangi bir sorunu çözebilecek bir ninja kodu olmadıkça. Dr. House kurallara uymaz, ancak hastane onu kovarsa, ölecek çok sayıda kurgusal insan olurdu. en.wikipedia.org/wiki/Gregory_House
jmort253

4

Bu sorunu ele almanın 3 yolu vardır:

  1. Kodlama kurallarıyla ilgili sorunları kontrol etmek için kaynak kodunun statik analizi. Gibi araçları kullanın cppcheck ve gelenler grammatech . Wikipedia'nın iyi bir listesi var: http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis . Genellikle çoğu kaynak kontrol sisteminde, check-in sırasında bu tür sorunları doğrudan kontrol edebileceğiniz kancalar bulunur. CVS kancaları için şu bağlantıya bakın: http://goo.gl/F1gd2 . Buna uyulmaması, check-in işleminin başarısız olması ve 3'ten fazla başarısızlık, geliştiricinin kendini takıma açıklaması gerektiği anlamına gelir.

  2. Kodlama işlemi sırasında, sorunları geliştiriciye işaretler. Seçtiğiniz IDE ile entegre özel komut dosyalarına sahip olmak bunu yapmanın harika bir yoludur. Bu bağlantıya göz atın: http://goo.gl/MM6c4

  3. Çevik süreçleri takip edin ve kod incelemesinin sprint'in bir parçası olduğundan emin olun


1
+1, splint (ve diğer birkaç lints) aracılığıyla değiştirilmiş her şeyi çalıştıran kancaların yanı sıra üstbilgileri gereksiz yere dahil etmediğimden emin olmak için araçlar, ayrıca girintinin boşluklar değil sekmeler olduğundan emin olmak için araçlarım var
Tim Post

Geliştiriciler bunları kullanmak zorunda değilse, teknik çözümler yardımcı olmayacaktır.
Robert Harvey

2

İşte 3 adımlık planım:

  1. Programcıları kov
  2. Bazı Yazılım Mühendislerini işe alın
  3. ...
  4. Kar!

: D

Tüm ciddiyetle, kod yazmaktan başka bir şey yapmaya inanmazlarsa, daha kapsamlı bir ekibe ihtiyacınız vardır. Çalıştığım bir programcı, bilgisayarında CM olarak farklı dizinler kullandı. Programcılarıyla neredeyse bir yıl boyunca savaştık (değişiklikler eski kodu kopyalayıp yapıştırdıkça hataları tanıtacağı için). Sonunda onları kovduk.


2
  1. Temel kuralları ihlal ettiklerinde onlara dikkat edin.
  2. Esnek olmayan kodları nedeniyle uygulayamadıkları özellik isteği ile karşılaşamayacakları hataları üretmelerini bekleyin.
  3. Onlara daha önce söylediklerinizi hatırlatın.
  4. Bir süre kendi boklarında boğulsunlar.
  5. Söz konusu kodu yeniden düzenlemek için zaman ayırın, hataları izole edin / yeni işlevler eklemek için altyapı sağlayın. Ne yaptığınızı açıklamak için biraz zaman ayırın.

Alternatif olarak, yapılacak en acımasız ama çok ikna edici şey, sıkı bir program göz önüne alındığında son derece kötü yazılmış bir kod tabanını korumalarına izin vermektir. : D
Ve sonra, bir değişiklik için, sıkı bir zamanlama verildiğinde, iyi yazılmış bir kod tabanı sürdürmelerine izin verin.

Genel olarak, belirli standartlara uyum sağlama konusunda isteksizlik, takım çalışmasında deneyim eksikliği anlamına gelir.

Sonunda insanlar sadece hatalardan ders alırlar. ASLA başkasının inatçılığına dayanan problemleri çözmeyin. Proje için gerçekten hayati önem taşıyorsa (örneğin, N gün içinde teslim etmezseniz şirketiniz dava açılacaktır), önce projeyi durdurun.


Bunu seviyorum. Senden nefret eden biri için harika bir tarif. ;)
Roman Zenka

@Roman Zenka: Muhtemelen evet. Ama eğer seçim nefret edilmekle hayal kırıklığına uğramak arasındaysa, takımda bir NNPP'ye sahip olduğunuz için, ilk seçeneği tercih ederim;)
back2dos

Bu noktada, bordrodan çıkarılmaları gerekiyor.
JeffO

Aslında bunun üzerinde çalıştım! Ve benden nefret etmiyorlar. Sonuç, herkes kendi bokunda rahattır. Bu da bu görevi çok zorlaştırıyor.
Sugra'yı

1

Programcı, bahsettiğiniz bu konulara karşı tutumlarını, bu şeylerin onlar için bir fayda veya avantaj sağlayacağını anlayana kadar değiştirmeyeceğini düşünüyorum. Onlara neden bu şeyleri yapmalarını istediğinizi açıklamaya çalışın. Daha da iyisi, avantajlarını deneyimlemelerine izin verin.


1

Bir profesyonel Yazılım Mühendisi kiralayın. Ve sonra en zayıf ateş. Sonra yavaş yavaş evlat edinemeyenleri değiştirin. Bu tür insanlara sahip olmak bazen uzun vadede kârdan daha fazla zarar getirir.

Burada ana fikir, profesyonellerin çoğu iş yapmaya başlayacağı ve başkalarını kovmanın değerli insan kaynağını azaltmayacağıdır.


1
Bu, liderlik becerileri ve daha az deneyimli bireylere rehberlik etme yeteneğini telafi etmenin harika bir yoludur. İkna becerileriniz emilirse, sizinle aynı fikirde olmayan herkesi kovmaya başlayın.
jmort253

@ jmort253, Eğer bir şansım varsa, sürüm kontrolüne bağlı olmayan her programcıyı düzenli olarak kovardım. Yazar sözlerinden, TÜM programcıların çok deneyimsiz olduklarını ve kendilerini öğrenmek ve geliştirmek istemediklerini anlıyorum.
Konstantin Petrukhnov

1

Biraz iğrenç, ama birkaç ay boyunca banyoda Code Complete bıraktı. Etkili olduğundan emin değilim, ama o zaman iyi bir fikir gibi görünüyordu.


0

Kurallara uymamanın sonuçları ve kurallara uymanın ödülleri nelerdir? Cevap aynı ise - hiçbir şey - herhangi bir çekiş elde etmek için iyi şanslar. Katmanlı bir yaklaşım öneriyorum. Öncelikle onları bir araya getirin ve kurallara uygun olup olmadıklarını tartışın. Bir sonraki adım, bunları kod incelemelerine dahil etmektir. Havuç ve çubukları da deneyebilirsiniz. Bir dosyayı bir gecede teslim alan herkes gibi bir şey, bir sonraki haftalık toplantıya çörek getirmelidir. Bir havuç, Vegas'ta bir hafta sonu için bir ay boyunca kurallara uyan herkes olabilir. İki kişilik.

Ya da en kötü faili kov ve gerisini terletmesine izin ver.


Eeep! Tek ödeme türünüz var mı? Yüzyıla gel adamım!
David Thornley

0

Bu kuralları kullanarak kaçınmak istediğiniz sonuçlara maruz kalmasını sağlayın, neden sorduğunuzu gerçekten anlamanın tek yolu budur, örneğin: düzeltmek zorunda oldukları küçük kontrollü bir karmaşa yapmak .


0

Eğer bu mürettebat değişiklikleri kontrol etmekte zorlanıyorsa, endişelerin ayrılmasına bağlı kalıyor ve sihirli sabitleri kodlamıyorsa, o zaman tüm mürettebatı ateşleyeceğim ve onları gerçekte mümkün olan en kısa sürede önemseyen gerçek programcılar 1 ile değiştirirdim . Bir kerede ya da kitlesel olarak söyleyemedim ama bu jokerler gitmek zorunda.

Tanımladığınız kodlama türü, tek kullanımlık komut dosyaları için uygundur. Gerçek bir uygulama bu şekilde kurulmaz. Profesyonel programcılar olarak ödeme alıyorlarsa, bu tür şeyleri bilmek onların görevidir.


1 Bu, genellikle kodlarını doğrudan ikili dosyaya veya eşit derecede saçma bir şeyler yazan hayali insanlar için şaka terimi olarak kullanılır. Burada şaka yapmıyorum. Oldukça çaylak bir programcıyım ve bunları söylemem gerekmeyecek çünkü zanaatımı önemsiyorum. Bunlar uğraştığınız gerçek programcılar değil.


Ateşleme kısmı hariç her şeye katılıyorum. Tüm deneyimli personelinizi, kod yazabilecek ancak sıfır alan bilgisine sahip kişilerle değiştirmek için, son tarihler ve müşteri aşamalarını karşılamak da dahil olmak üzere üzerinde çalıştığınız diğer tüm kritik görevleri bırakarak iyi şanslar.
jmort253

0

Bir yöneticinin işi çalışanın arkadaşı olmak değil, bazen kötü adam olmanız gerekir. Kodlama standartlarını ve taahhütlerini uygulamak, yasaklanmış mimariyi takip etmeyi reddetmek, öngörülen araçları kullanmamak vb. Popüler olmamanız gereken zamanlardır.

Politikaları açık bir şekilde ifade edin. Resmi kod incelemeleri yapın ve politikalara uyulup uyulmadığını kontrol edin. Kod gözden geçirmeyle ilgili tüm sorunlar kararlaştırılıncaya kadar başka bir göreve geçmelerine izin vermeyin.

Politika kod işlememeyle ilgiliyse, istendiğinde bunu yapamazlarsa, bu yazılı bir uyarı gerektirir. Eğer kod işlemiyorlarsa, endişelendiğiniz sürece hiç yazmamışlardır.

İyileştirmek için makul bir şans verildikten sonra iyileşmezlerse, onları ateşleyin. Profesyonel olmayan geliştiriciler, ne tür bir kod yazarlarsa yazsınlar, ekibinizde bir sürükle. Profesyonellik eksiklikleri ile başkalarını etkiliyorlar ve bu hoşgörülemez. Hiçbir durumda tutmaları iyi insanlar değildir. İyi geliştiriciler kodlarını taahhüt ederler, iyi geliştiriciler kendileriyle aynı fikirde olmasalar bile mimari kararları takip ederler ve iyi geliştiriciler zor kod kullanmazlar. Kovboy kodlayıcılardan kurtularak baş ağrısı dışında hiçbir şeyi kaçırmayacaksınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.